{
  "openapi": "3.1.0",
  "info": {
    "title": "Lensmor API",
    "version": "0.27.0",
    "description": "Lensmor Event Intelligence API for event discovery, exhibitor research, personnel lookup, credits, and profile matching.",
    "license": {
      "name": "Lensmor Terms of Service",
      "url": "https://www.lensmor.com/terms"
    }
  },
  "servers": [
    {
      "url": "https://platform.lensmor.com"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Credits",
      "description": "Inspect the credit balance available to the authenticated API key owner."
    },
    {
      "name": "Actions",
      "description": "Preflight access and credit-sensitive actions before executing them."
    },
    {
      "name": "Events",
      "description": "Discover, inspect, score, rank, and unlock trade show event records."
    },
    {
      "name": "Exhibitors",
      "description": "Search and inspect exhibiting companies and their related events."
    },
    {
      "name": "Personnel",
      "description": "Browse event personnel, related events, LinkedIn activity, and outreach content."
    },
    {
      "name": "Contacts",
      "description": "Search contacts and run asynchronous email or phone unlock workflows."
    },
    {
      "name": "Profile Matching",
      "description": "Apply a buyer profile to rank events and recommend exhibitors."
    }
  ],
  "paths": {
    "/external/credits/balance": {
      "get": {
        "tags": [
          "Credits"
        ],
        "summary": "Get credits balance",
        "description": "Return the current credit position for the authenticated API key owner without spending credits.\n\nUse this endpoint before and after any workflow that can consume credits, including event access, Visitor access, contact enrichment, and charged company searches. The response separates subscription, add-on, and gift balances so a client can show both the usable total and the buckets that contribute to it.\n\nThis is a read-only account check. A successful response does not reserve credits or guarantee that a later paid action will still have sufficient balance, so refresh the balance immediately before user-confirmed spending and again after the action completes.",
        "operationId": "getExternalCreditsBalance",
        "responses": {
          "200": {
            "description": "Credits balance",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditBalance"
                },
                "example": {
                  "totalAmount": 45050,
                  "totalBalance": 38050,
                  "subscriptionAmount": 35000,
                  "subscriptionBalance": 30000,
                  "addonAmount": 10000,
                  "addonBalance": 8000,
                  "addonExpireAt": 1784851200000,
                  "giftAmount": 50,
                  "giftBalance": 50,
                  "resetAt": 1714521600000
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/actions/precheck": {
      "post": {
        "tags": [
          "Actions"
        ],
        "summary": "Precheck an external action",
        "description": "Evaluate whether a supported external action can run and what it is expected to cost, without executing the action or charging credits.\n\nUse precheck immediately before event-access, Visitor-access, contact-unlock, and other action-specific workflows. Inspect `allowed`, `should_charge`, `credits`, and `reason_code` to decide whether to continue, ask the user for confirmation, or explain why the action is unavailable.\n\nPrecheck is advisory and read-only: it does not reserve credits, create a task, or lock the target state. Send the same action type and identifiers to the execution endpoint promptly, and still handle state or balance changes returned by that endpoint.",
        "operationId": "precheckExternalAction",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ActionPrecheckRequest"
              },
              "example": {
                "action_type": "query_event_personnel",
                "call_source": "api",
                "params": {
                  "event_id": "26855"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Precheck decision envelope",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ActionPrecheckResponse"
                },
                "example": {
                  "ok": true,
                  "action_type": "query_event_personnel",
                  "allowed": true,
                  "should_charge": false,
                  "credits": 0,
                  "reason_code": "ok",
                  "biz_code": "",
                  "detail": {
                    "event_id": "26855",
                    "access_mode": "preview",
                    "preview_limit": 50,
                    "unlock_action_type": "unlock_event_contacts",
                    "unlock_credits": 2000
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/list": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "List events",
        "description": "Browse the Lensmor event catalog with keyword, geography, date, event-type, quality, Sponsor Match, and Visitor-data filters.\n\nUse this endpoint for broad discovery, search pages, and the first step of an event workflow. Returned `id` and `eventId` values can be passed to event detail, exhibitor, personnel, scoring, ranking, recommendation, and access-unlock endpoints.\n\nFilters narrow the catalog and pagination is one-based. Use `sponsor_match_starred=1` or `0` for Sponsor Match state and `has_visitors=1` or `0` for Visitor-data availability. Returned `hasVisitors` is an availability signal; it does not mean the caller has unlocked Visitor data. No matches return `200 OK` with an empty `items` array.",
        "operationId": "listEvents",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "name": "keyword",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Search event names and related event text by keyword.",
            "example": "CES"
          },
          {
            "name": "country",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            },
            "description": "Filter events by country name.",
            "example": "United States"
          },
          {
            "name": "city",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            },
            "description": "Filter events by city name.",
            "example": "Las Vegas"
          },
          {
            "name": "date_start_from",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive lower bound for the event start date in `YYYY-MM-DD` format.",
            "example": "2025-01-01"
          },
          {
            "name": "date_start_to",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "description": "Inclusive upper bound for the event start date in `YYYY-MM-DD` format.",
            "example": "2025-12-31"
          },
          {
            "name": "event_type",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by one or more event-type labels. Comma-separated input is supported.",
            "example": [
              "In-person"
            ]
          },
          {
            "name": "quality",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by one or more quality labels. Comma-separated input is supported.",
            "example": [
              "Verified"
            ]
          },
          {
            "name": "sponsor_match_starred",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "description": "Filter by Sponsor Match starred state: `1` for starred or `0` for not starred.",
            "example": 1
          },
          {
            "name": "has_visitors",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ]
            },
            "description": "Filter by registered Visitor-data availability: `1` when available or `0` when unavailable.",
            "example": 1
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "8458",
                      "eventId": "26855",
                      "name": "CES 2025",
                      "nickname": "Consumer Electronics Show 2025",
                      "description": "Consumer technology trade show in Las Vegas.",
                      "url": "https://www.ces.tech/",
                      "dateStart": "2025-01-07",
                      "dateEnd": "2025-01-10",
                      "venue": "Las Vegas Convention Center",
                      "city": "Las Vegas",
                      "region": "Nevada",
                      "country": "United States",
                      "exhibitorCount": 3259,
                      "hasVisitors": true,
                      "sponsorMatchStarred": 0,
                      "image": "https://example.com/ces-image.png",
                      "dataSource": "Lensmor"
                    }
                  ],
                  "total": 42,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 3,
                  "hasMore": true
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/{id}": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "Get event detail",
        "description": "Retrieve the canonical detailed record for one Lensmor event after discovery or selection.\n\nUse this endpoint when a product needs venue, dates, description, geography, categories, topics, pricing, coordinates, coverage counts, or other event-level metadata that is not necessary in a lightweight list or brief view. The path accepts the event `id` or `eventId` returned by public event responses.\n\nThis read-only call does not unlock event, exhibitor, personnel, or Visitor access. Treat `hasVisitors` as an availability signal only, then inspect event-scoped list semantics or run an action precheck before a paid unlock.",
        "operationId": "getEventDetail",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdPath"
          }
        ],
        "responses": {
          "200": {
            "description": "Event detail",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "event"
                  ],
                  "properties": {
                    "event": {
                      "$ref": "#/components/schemas/EventDetail"
                    }
                  }
                },
                "example": {
                  "event": {
                    "id": "8458",
                    "eventId": "26855",
                    "name": "CES 2025",
                    "description": "Consumer technology trade show in Las Vegas.",
                    "url": "https://www.ces.tech/",
                    "dateStart": "2025-01-07",
                    "dateEnd": "2025-01-10",
                    "venue": "Las Vegas Convention Center",
                    "city": "Las Vegas",
                    "region": "Nevada",
                    "country": "United States",
                    "exhibitorCount": 3259,
                    "hasVisitors": true,
                    "sponsorMatchStarred": 0,
                    "dataSource": "Lensmor"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/brief": {
      "get": {
        "tags": [
          "Events"
        ],
        "summary": "Get event brief",
        "description": "Fetch a lightweight summary for one event, including core identity, coverage counts, top categories, and data freshness.\n\nUse this endpoint for compact cards, quick previews, background refreshes, or any UI that does not need the full event-detail shape. Pass the `event_id` returned by discovery or recommendation endpoints, and treat unavailable optional values according to their documented nullability.\n\nThe brief is read-only and is not an access-unlock response. Use event detail when you need the complete profile. Use event-scoped exhibitor or personnel lists to inspect available records and preview/full-access semantics before spending credits.",
        "operationId": "getEventBrief",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Event brief",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "event",
                    "summary"
                  ],
                  "properties": {
                    "event": {
                      "$ref": "#/components/schemas/EventItem"
                    },
                    "summary": {
                      "type": "object",
                      "properties": {
                        "attendeeCount": {
                          "type": [
                            "integer",
                            "null"
                          ]
                        },
                        "exhibitorCount": {
                          "type": "integer"
                        },
                        "topCategories": {
                          "type": "array",
                          "items": {
                            "type": "string"
                          }
                        },
                        "dataFreshness": {
                          "type": "string"
                        }
                      }
                    }
                  }
                },
                "example": {
                  "event": {
                    "id": "123",
                    "eventId": "139574",
                    "name": "NRF 2026",
                    "description": "Retail industry event",
                    "url": "https://example.com/events/nrf-2026",
                    "dateStart": "2026-01-12",
                    "dateEnd": "2026-01-15",
                    "venue": "Javits Center",
                    "city": "New York",
                    "region": "NY",
                    "country": "United States",
                    "exhibitorCount": 950,
                    "sponsorMatchStarred": 0,
                    "dataSource": "Lensmor"
                  },
                  "summary": {
                    "attendeeCount": 40000,
                    "exhibitorCount": 950,
                    "topCategories": [],
                    "dataFreshness": "database_snapshot"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/fit-score": {
      "post": {
        "tags": [
          "Events"
        ],
        "summary": "Score one event",
        "description": "Calculate how well one known event matches the authenticated caller's current profile context without unlocking the event.\n\nUse this endpoint when a user has already selected an event and needs a focused fit assessment. The response combines the event record, a numeric score, a recommendation label, and explanatory breakdown data. For a supplied shortlist of several events, use event ranking instead; for discovery from company or audience inputs, use profile-matching recommendations.\n\nScores are profile-dependent and can change when profile data or event data changes. Store the event identifier as the stable reference and treat the score and rationale as a point-in-time recommendation.",
        "operationId": "scoreEventFit",
        "requestBody": {
          "$ref": "#/components/requestBodies/EventIdBody"
        },
        "responses": {
          "201": {
            "description": "Event fit score",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventFitScore"
                },
                "example": {
                  "event": {
                    "id": "123",
                    "eventId": "139574",
                    "name": "NRF 2026",
                    "description": "Retail industry event",
                    "url": "https://example.com/events/nrf-2026",
                    "dateStart": "2026-01-12",
                    "dateEnd": "2026-01-15",
                    "venue": "Javits Center",
                    "city": "New York",
                    "region": "NY",
                    "country": "United States",
                    "exhibitorCount": 950,
                    "sponsorMatchStarred": 0,
                    "dataSource": "Lensmor"
                  },
                  "score": 8.1,
                  "recommendation": "recommended",
                  "breakdown": {
                    "profile_match": 8.1,
                    "matched_exhibitor_density": 1.9,
                    "event_scale": 9.5
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/rank": {
      "post": {
        "tags": [
          "Events"
        ],
        "summary": "Rank events",
        "description": "Rank a caller-supplied shortlist of event identifiers against the authenticated user's current profile.\n\nUse this endpoint after another workflow has produced candidate events—for example event search, CRM input, exhibitor/personnel history, or a user-curated shortlist. The response orders the candidates and returns match scores and reasons where available.\n\nThis endpoint ranks only the identifiers supplied; it is not a database-wide discovery call and it does not unlock event data. Invalid or unavailable identifiers can prevent a complete ranking, so retain the original shortlist and handle missing candidates explicitly.",
        "operationId": "rankEvents",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "event_ids"
                ],
                "properties": {
                  "event_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "Event identifiers to rank against the authenticated user's current profile. Runtime validation permits an empty array.",
                    "example": [
                      "26855",
                      "139574"
                    ]
                  }
                }
              },
              "example": {
                "event_ids": [
                  "139574",
                  "139575"
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Ranked events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "items"
                  ],
                  "properties": {
                    "items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/EventRankItem"
                      }
                    }
                  }
                },
                "example": {
                  "items": [
                    {
                      "event_id": "139574",
                      "name": "NRF 2026",
                      "rank": 1,
                      "match_score": 0.86,
                      "reasons": []
                    },
                    {
                      "event_id": "139575",
                      "name": "Shoptalk 2026",
                      "rank": 2,
                      "match_score": 0.79,
                      "reasons": []
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/{id}/unlock": {
      "post": {
        "tags": [
          "Events"
        ],
        "summary": "Unlock event access",
        "description": "Unlock the base event access layer so event-scoped exhibitor and personnel endpoints can return complete coverage beyond preview limits.\n\nUse this endpoint only after the user has selected an event and reviewed the preview semantics from exhibitor or personnel lists. The first successful base unlock can consume `2,000` credits. Repeating the call for an already unlocked event is idempotent and should not charge again.\n\nThis endpoint does not unlock the separate registered Visitor layer. Use action precheck before execution, provide `x-call-source` for attribution, and use Visitor unlock or full-access unlock only when Visitor data is also required.",
        "operationId": "unlockEvent",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdPath"
          },
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "responses": {
          "201": {
            "description": "Event unlock result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventUnlockResult"
                },
                "example": {
                  "success": true,
                  "alreadyUnlocked": false,
                  "creditsUsed": 2000,
                  "balanceAfter": {
                    "subscriptionBalance": 0,
                    "permanentBalance": 451021,
                    "totalBalance": 451021,
                    "unlimited": false
                  },
                  "event": {
                    "id": "8458",
                    "eventId": "26855",
                    "name": "CES 2025"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/{id}/visitors/unlock": {
      "post": {
        "tags": [
          "Events"
        ],
        "summary": "Unlock event visitor access",
        "description": "Unlock the registered Visitor data layer for an event that already has base event access.\n\nUse this endpoint when Visitor records are available and the caller needs that source in addition to base exhibitor and personnel coverage. Run action precheck with `unlock_event_visitors` first. A first successful Visitor unlock consumes `3,000` credits, requires an active subscription, and requires Visitor data to be available for the event.\n\nThe operation is idempotent for an already unlocked Visitor layer. It does not replace the base event unlock prerequisite. Handle `409` state conflicts and availability failures as workflow states rather than blindly retrying the paid request.",
        "operationId": "unlockEventVisitors",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdPath"
          },
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "responses": {
          "200": {
            "description": "Business-error envelope when the caller has no active paid subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureUnavailableBusinessError"
                },
                "example": {
                  "code": 400,
                  "message": "This feature is not available to free users, please upgrade to continue",
                  "errorKey": "USER_HAS_NO_FEATURE",
                  "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
                }
              }
            }
          },
          "201": {
            "description": "Visitor access unlock result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventVisitorUnlockResult"
                },
                "example": {
                  "success": true,
                  "alreadyUnlocked": false,
                  "creditsSpent": 3000,
                  "balanceAfter": {
                    "totalAmount": 45050,
                    "totalBalance": 35050,
                    "subscriptionAmount": 35000,
                    "subscriptionBalance": 27000,
                    "addonAmount": 10000,
                    "addonBalance": 8000,
                    "addonExpireAt": 1784851200000,
                    "giftAmount": 50,
                    "giftBalance": 50,
                    "resetAt": 1785542400000
                  },
                  "event": {
                    "id": "8458",
                    "eventId": "26855",
                    "name": "CES 2025"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/events/{id}/full-access/unlock": {
      "post": {
        "tags": [
          "Events"
        ],
        "summary": "Unlock full event access",
        "description": "Atomically request all available access layers for one event and pay only for layers that are still locked.\n\nUse this endpoint when the user wants both base exhibitor/personnel coverage and registered Visitor coverage in one confirmed action. Base access costs `2,000` credits and Visitor access costs `3,000` credits, so a fully locked event can consume up to `5,000` credits. Already unlocked layers are not charged again.\n\nRun action precheck with `unlock_event_full_access` before execution. The response identifies which layers changed, whether Visitor access was skipped, the exact credits used, and the balance afterward. If Visitor data is unavailable and only base access is required, use the base event unlock endpoint.",
        "operationId": "unlockEventFullAccess",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdPath"
          },
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "responses": {
          "200": {
            "description": "Business-error envelope when the caller has no active paid subscription",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeatureUnavailableBusinessError"
                },
                "example": {
                  "code": 400,
                  "message": "This feature is not available to free users, please upgrade to continue",
                  "errorKey": "USER_HAS_NO_FEATURE",
                  "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
                }
              }
            }
          },
          "201": {
            "description": "Full event access unlock result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventFullAccessUnlockResult"
                },
                "example": {
                  "success": true,
                  "alreadyUnlocked": false,
                  "eventUnlocked": true,
                  "visitorUnlocked": true,
                  "visitorSkipped": false,
                  "totalCreditsUsed": 5000,
                  "balanceAfter": {
                    "subscriptionBalance": 25000,
                    "permanentBalance": 50,
                    "totalBalance": 33050,
                    "unlimited": false
                  },
                  "event": {
                    "id": "8458",
                    "eventId": "26855",
                    "name": "CES 2025"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/exhibitors/list": {
      "get": {
        "tags": [
          "Exhibitors"
        ],
        "summary": "List event exhibitors",
        "description": "List exhibitors within one selected event, with company filters, optional personnel hints, pagination, and preview/full-access semantics.\n\nUse this endpoint to build an event exhibitor directory, filter companies by keyword, country, category, or industry, and collect exhibitor IDs for profile or related-event calls. `personnelLimit` can request a best-effort nested personnel sample; use the event personnel endpoint when contacts are required.\n\nAlways inspect `semantics.accessMode`, counts, page state, and unlock guidance. Preview results can be intentionally limited until base event access is unlocked. No matches return an empty page, while an unknown event returns an error.",
        "operationId": "listExhibitors",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdQuery"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "name": "keyword",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Search exhibitor company names and related company text within the event.",
            "example": "Acme"
          },
          {
            "name": "country",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            },
            "description": "Filter exhibitors by company country.",
            "example": "United States"
          },
          {
            "$ref": "#/components/parameters/CategoryArray"
          },
          {
            "$ref": "#/components/parameters/IndustryArray"
          },
          {
            "name": "jobTitle",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by one or more nested personnel job-title terms.",
            "example": [
              "VP Marketing"
            ]
          },
          {
            "name": "managementLevel",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by normalized personnel management levels such as `vp` or `c_suite`.",
            "example": [
              "vp"
            ]
          },
          {
            "name": "department",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by normalized personnel departments such as `marketing` or `sales`.",
            "example": [
              "marketing"
            ]
          },
          {
            "name": "personnelLimit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Maximum best-effort nested personnel samples per exhibitor. Use `0` or omit the parameter for no nested sample.",
            "example": 3
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated exhibitors with access semantics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExhibitorPageWithSemantics"
                },
                "example": {
                  "items": [
                    {
                      "id": "456",
                      "companyName": "Acme Retail Systems",
                      "domain": "acme.example",
                      "website": "https://acme.example",
                      "industry": "Retail Technology",
                      "country": "United States",
                      "matched_event_ids": [
                        "139574"
                      ]
                    }
                  ],
                  "total": 87,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 5,
                  "hasMore": true,
                  "recommendationProcessing": false,
                  "recommendationProcessingFeature": "none",
                  "semantics": {
                    "accessMode": "preview",
                    "previewLimit": 50,
                    "counts": {
                      "actualTotal": 87,
                      "visibleTotal": 50,
                      "remainingLockedCount": 37
                    },
                    "pageState": {
                      "requestedPage": 1,
                      "accessible": true,
                      "maxAccessiblePage": 1
                    },
                    "unlock": {
                      "requiredForMoreResults": true,
                      "actionType": "unlock_event_exhibitors",
                      "credits": 2000
                    },
                    "guidance": {
                      "code": "preview_results_truncated",
                      "message": "This event is locked. Only the first 50 matching exhibitors are currently accessible. Unlock the event to access the remaining matching results."
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/exhibitors/search": {
      "post": {
        "tags": [
          "Exhibitors"
        ],
        "summary": "Search exhibitors by company context",
        "description": "Search Lensmor exhibitor records from company context such as a public company URL or a target-audience description.\n\nUse this endpoint when the workflow starts from a company or buyer profile rather than a known event. Provide at least one of `company_url` or `target_audience`; providing both gives the matcher more context. The result is a paginated exhibitor list that can feed exhibitor profile, related-event, or contact discovery workflows.\n\nThis is broader contextual matching, not an exact company-name lookup. Use the company-name endpoint for precision-first name matching and the exhibitor event-search endpoint when the desired output is events rather than companies.",
        "operationId": "searchExhibitors",
        "requestBody": {
          "$ref": "#/components/requestBodies/ExhibitorSearchBody"
        },
        "responses": {
          "201": {
            "description": "Paginated exhibitors",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExhibitorPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "456",
                      "companyName": "Acme Retail Systems",
                      "domain": "acme.example",
                      "website": "https://acme.example",
                      "industry": "Retail Technology",
                      "country": "United States",
                      "matched_event_ids": [
                        "139574"
                      ]
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/exhibitors/search-by-company-name": {
      "post": {
        "tags": [
          "Exhibitors"
        ],
        "summary": "Search exhibitors by company name",
        "description": "Run a precision-first lookup for exhibitor company records from a required company name.\n\nUse this endpoint when the input is a known company name and the desired output is exhibitor IDs and enriched company records. Matching intentionally favors precision over broad fuzzy recall, so ambiguous or weak input can return an empty page. Reuse the selected exhibitor ID for profile and related-event calls instead of repeating the paid search.\n\nA non-empty result consumes `50` credits; an empty result consumes `0` credits. Check the credit balance and confirm charged searches in user-facing or bulk workflows. Use exhibitor event search when the desired output is the events associated with the company.",
        "operationId": "searchExhibitorsByCompanyName",
        "parameters": [
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/CompanyNameBody"
        },
        "responses": {
          "201": {
            "description": "Paginated exhibitors",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExhibitorPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "456",
                      "companyName": "Acme Retail Systems",
                      "domain": "acme.example",
                      "website": "https://acme.example",
                      "industry": "Retail Technology",
                      "country": "United States",
                      "matched_event_ids": [
                        "139574"
                      ]
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/exhibitors/search-events": {
      "post": {
        "tags": [
          "Exhibitors"
        ],
        "summary": "Search events by exhibitor company name",
        "description": "Find deduplicated events associated with exhibitor companies matching a required company name. Use this for account planning or CRM enrichment without first resolving `exhibitor_id`. The precision-first matcher can return no result for incomplete names. A non-empty result consumes `50` credits; an empty result consumes `0`. `sponsor_match_starred` optionally selects starred or non-starred events.\n\n`attendance_scope` accepts `all` (default), `exhibitor`, or `visitor`. `exhibitor` includes events with exhibitor evidence, even when visitor evidence is present. `visitor` returns visitor-only events and excludes exhibitor evidence. Each event includes `attendance_identity`; visitor-only results can have an empty `matchedExhibitors` array.",
        "operationId": "searchEventsByExhibitorCompanyName",
        "parameters": [
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "requestBody": {
          "$ref": "#/components/requestBodies/SearchEventsByCompanyNameBody"
        },
        "responses": {
          "200": {
            "description": "Business-error envelope when another request already occupies the per-user concurrency slot",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConcurrencyLimitBusinessError"
                },
                "example": {
                  "code": 429,
                  "message": "Too many concurrent requests for this endpoint",
                  "errorKey": "USER_CONCURRENCY_LIMIT_EXCEEDED",
                  "data": null,
                  "details": null,
                  "traceId": "trace-123"
                }
              }
            }
          },
          "201": {
            "description": "Paginated events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventReverseSearchPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "123",
                      "eventId": "139574",
                      "name": "Shoptalk 2026",
                      "dateStart": "2026-03-15",
                      "dateEnd": "2026-03-18",
                      "city": "Las Vegas",
                      "country": "United States",
                      "sponsorMatchStarred": 1,
                      "dataSource": "Lensmor",
                      "matchedExhibitors": [
                        {
                          "id": "456",
                          "companyName": "Acme Retail Systems"
                        }
                      ],
                      "attendance_identity": [
                        "exhibitor",
                        "visitor"
                      ]
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/exhibitors/profile": {
      "get": {
        "tags": [
          "Exhibitors"
        ],
        "summary": "Get exhibitor profile",
        "description": "Retrieve the detailed public company profile for one known exhibitor identifier.\n\nUse this endpoint after selecting an exhibitor from an event list, contextual search, company-name search, or recommendation result. The response is suited to company profile cards and includes enrichment such as description, industry, company size, country, website, LinkedIn identity, and compact event references when available. Store the exhibitor ID as the stable Lensmor reference for follow-up calls.\n\nThis read-only call does not unlock event access or contact data. Use the related-events endpoint for a paginated event history and personnel/contact endpoints when the next step is people discovery.",
        "operationId": "getExhibitorProfile",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExhibitorIdQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Exhibitor profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExhibitorProfile"
                },
                "example": {
                  "id": "456",
                  "companyName": "Acme Retail Systems",
                  "domain": "acme.example",
                  "website": "https://acme.example",
                  "industry": "Retail Technology",
                  "employeeCount": 220,
                  "country": "United States",
                  "fundingRound": "Series B",
                  "matched_event_ids": [
                    "139574"
                  ],
                  "events": [
                    {
                      "id": "123",
                      "eventId": "139574",
                      "name": "NRF 2026"
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/exhibitors/events": {
      "get": {
        "tags": [
          "Exhibitors"
        ],
        "summary": "List exhibitor related events",
        "description": "Return a paginated list of Lensmor events for a known `exhibitor_id`. Use it after resolving an exhibitor profile to browse company event associations. Follow `hasMore` and increment `page` for more results; an exhibitor with no associated events returns an empty page, while an unknown ID returns an error.\n\n`attendance_scope` accepts `all` (default), `exhibitor`, or `visitor`. `all` returns events with known attendance evidence. `exhibitor` includes events with exhibitor evidence, even when visitor evidence is also present. `visitor` returns visitor-only events and excludes events with exhibitor evidence. Each item includes an event-scoped `attendance_identity` array. If you only have a company name, use exhibitor event search.",
        "operationId": "listExhibitorEvents",
        "parameters": [
          {
            "$ref": "#/components/parameters/ExhibitorIdQuery"
          },
          {
            "$ref": "#/components/parameters/CompanyAttendanceScopeQuery"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ExhibitorRelatedEventPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "123",
                      "eventId": "139574",
                      "name": "NRF 2026",
                      "dateStart": "2026-01-12",
                      "dateEnd": "2026-01-15",
                      "city": "New York",
                      "country": "United States",
                      "attendance_identity": [
                        "visitor"
                      ]
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request GET \\\n  --url 'https://platform.lensmor.com/external/exhibitors/events?exhibitor_id=456&attendance_scope=visitor&page=1&pageSize=20' \\\n  --header 'Authorization: Bearer <token>'"
          }
        ]
      }
    },
    "/external/personnel/list": {
      "get": {
        "tags": [
          "Personnel"
        ],
        "summary": "List event personnel",
        "description": "List people associated with one event, with optional exhibitor, department, seniority, text, and attendee-source filtering.\n\nUse this endpoint to build attendee exploration, segment people within an event, and collect personnel IDs for profile, LinkedIn activity, contact unlock, or outreach workflows. `sourceType` accepts one or more event-scoped values—`exhibitor`, `social`, or `visitors`—comma-separated or repeated; returned arrays can still contain multiple non-exclusive labels.\n\nInspect the returned access semantics and counts. Base-event preview/full mode does not by itself confirm separate Visitor-layer access. This endpoint is read-only and does not unlock email addresses, phone numbers, or LinkedIn activity.",
        "operationId": "listPersonnel",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdQuery"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "name": "pageSize",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 50
            },
            "description": "Maximum personnel records requested per page. The default and maximum are `50` for this endpoint.",
            "example": 50
          },
          {
            "name": "exhibitor_id",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Limit results to one exhibitor within the selected event.",
            "example": "4182"
          },
          {
            "name": "department",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 100
            },
            "description": "Filter by normalized department label.",
            "example": "marketing"
          },
          {
            "name": "level",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 50
            },
            "description": "Filter by normalized seniority or management level.",
            "example": "vp"
          },
          {
            "name": "search_query",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "description": "Search the person's name or job title within the event-scoped result set.",
            "example": "Jane Doe"
          },
          {
            "name": "sourceType",
            "in": "query",
            "description": "Filter by one or more event-scoped attendee-source labels: `exhibitor`, `social`, or `visitors`. Send comma-separated values or repeat the query parameter.",
            "schema": {
              "type": "string",
              "maxLength": 200
            },
            "example": "social,visitors"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated contacts with access semantics",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPageWithSemantics"
                },
                "example": {
                  "items": [
                    {
                      "id": "789",
                      "fullName": "Jane Smith",
                      "title": "VP of Retail Technology",
                      "companyName": "Acme Retail Systems",
                      "sourceType": [
                        "exhibitor",
                        "social"
                      ],
                      "email": null,
                      "phone": null,
                      "contactUnlockStatus": "locked",
                      "phoneUnlockStatus": null,
                      "eventCount": 5,
                      "outreachMessageStatus": null,
                      "outreachMessageChannels": []
                    }
                  ],
                  "total": 42,
                  "page": 1,
                  "pageSize": 50,
                  "totalPages": 1,
                  "hasMore": false,
                  "semantics": {
                    "accessMode": "preview",
                    "previewLimit": 50
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/personnel/profile": {
      "get": {
        "tags": [
          "Personnel"
        ],
        "summary": "Get personnel profile",
        "description": "Retrieve the public professional profile for one known Lensmor personnel identifier.\n\nUse this endpoint after a person is selected from event personnel, contact search, or LinkedIn-based event lookup. It is designed to confirm identity, company and role context, normalized department/seniority metadata, aggregated attendee-source labels, and the current contact access state before a follow-up action.\n\nThis read-only profile call does not unlock email, phone, or LinkedIn activity. `sourceType` can aggregate non-exclusive labels across associated events; use the event personnel list when event-specific source context is required.",
        "operationId": "getPersonnelProfile",
        "parameters": [
          {
            "$ref": "#/components/parameters/PersonnelIdQuery"
          }
        ],
        "responses": {
          "200": {
            "description": "Personnel profile",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactItem"
                },
                "example": {
                  "id": "789",
                  "fullName": "Jane Smith",
                  "title": "VP of Retail Technology",
                  "department": "Technology",
                  "seniorityLevel": "vp",
                  "linkedinUrl": "https://linkedin.com/in/jane-smith",
                  "companyName": "Acme Retail Systems",
                  "sourceType": [
                    "exhibitor",
                    "visitors"
                  ],
                  "email": null,
                  "phone": null,
                  "contactUnlockStatus": "locked",
                  "phoneUnlockStatus": null,
                  "eventCount": 5,
                  "outreachMessageStatus": null,
                  "outreachMessageChannels": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/personnel/events": {
      "get": {
        "tags": [
          "Personnel"
        ],
        "summary": "List personnel related events",
        "description": "Return paginated events associated with a known `personnel_id`. Use it after resolving the person to browse event history or current associations. Follow `hasMore` and increment `page` for additional results. This lookup does not expose or unlock contact data. Use the LinkedIn URL or exact-name lookup when a Lensmor personnel ID is unavailable.\n\n`attendance_scope` accepts `all` (default), `exhibitor_employee`, or `visitor`. `all` returns events with known attendance evidence. `exhibitor_employee` includes events with employee evidence, even when visitor evidence is also present. `visitor` returns visitor-only events and excludes events with exhibitor-employee evidence. Each item includes an event-scoped `attendance_identity` array.",
        "operationId": "listPersonnelEvents",
        "parameters": [
          {
            "$ref": "#/components/parameters/PersonnelIdQuery"
          },
          {
            "$ref": "#/components/parameters/PersonnelAttendanceScopeQuery"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PersonnelRelatedEventPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "501",
                      "eventId": "139574",
                      "name": "Retail Technology Expo 2026",
                      "attendance_identity": [
                        "visitor"
                      ]
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request GET \\\n  --url 'https://platform.lensmor.com/external/personnel/events?personnel_id=789&attendance_scope=visitor&page=1&pageSize=20' \\\n  --header 'Authorization: Bearer <token>'"
          }
        ]
      }
    },
    "/external/personnel/events/by-linkedin": {
      "get": {
        "tags": [
          "Personnel"
        ],
        "summary": "List personnel related events by LinkedIn URL",
        "description": "Normalize a public LinkedIn profile URL, resolve its matching Lensmor personnel record, and return the person plus paginated related events. Use this lookup when a LinkedIn URL is the stable starting identifier; a URL that cannot be resolved returns not found. The call does not unlock contact data. Follow `hasMore` for additional event pages.\n\n`attendance_scope` accepts `all` (default), `exhibitor_employee`, or `visitor`. `all` returns events with known attendance evidence. `exhibitor_employee` includes dual-identity events. `visitor` returns visitor-only events and excludes events with exhibitor-employee evidence. Each event includes an event-scoped `attendance_identity` array.",
        "operationId": "listPersonnelEventsByLinkedin",
        "parameters": [
          {
            "name": "linkedin_url",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "maxLength": 500
            },
            "description": "Public LinkedIn profile URL used for normalized personnel matching.",
            "example": "https://www.linkedin.com/in/jane-doe"
          },
          {
            "$ref": "#/components/parameters/PersonnelAttendanceScopeQuery"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          }
        ],
        "responses": {
          "200": {
            "description": "Personnel profile and related events",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "personnel",
                    "events"
                  ],
                  "properties": {
                    "personnel": {
                      "$ref": "#/components/schemas/ContactItem"
                    },
                    "events": {
                      "$ref": "#/components/schemas/PersonnelRelatedEventPage"
                    }
                  }
                },
                "example": {
                  "personnel": {
                    "id": "789",
                    "fullName": "Jane Smith",
                    "linkedinUrl": "https://linkedin.com/in/jane-smith",
                    "email": null,
                    "phone": null,
                    "contactUnlockStatus": "locked",
                    "phoneUnlockStatus": null,
                    "eventCount": 5
                  },
                  "events": {
                    "items": [
                      {
                        "id": "501",
                        "eventId": "139574",
                        "name": "Retail Technology Expo 2026",
                        "attendance_identity": [
                          "visitor"
                        ]
                      }
                    ],
                    "total": 1,
                    "page": 1,
                    "pageSize": 20,
                    "totalPages": 1,
                    "hasMore": false
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request GET \\\n  --url 'https://platform.lensmor.com/external/personnel/events/by-linkedin?linkedin_url=https%3A%2F%2Fwww.linkedin.com%2Fin%2Fjane-smith&attendance_scope=visitor&page=1&pageSize=20' \\\n  --header 'Authorization: Bearer <token>'"
          }
        ]
      }
    },
    "/external/personnel/events/by-name": {
      "get": {
        "tags": [
          "Personnel"
        ],
        "summary": "Search personnel related events by name",
        "description": "Find paginated, deduplicated events for up to 50 personnel records with the exact full name. Matching ignores case and surrounding whitespace. Date filters use event start dates; `date_start_from` defaults to `2026-01-01`. A non-empty result consumes `50` credits; an empty result consumes `0`. Up to `10 requests` can run concurrently per user.\n\n`attendance_scope` accepts `all` (default), `exhibitor_employee`, or `visitor`. `all` includes known attendance evidence. `exhibitor_employee` includes dual-identity events. `visitor` returns visitor-only events and excludes exhibitor-employee evidence. Evidence is combined per event across matched people before filtering. Each event returns the complete `attendance_identity` array.",
        "operationId": "searchPersonnelEventsByName",
        "parameters": [
          {
            "name": "person_name",
            "in": "query",
            "required": true,
            "description": "Exact full name. Matching is case-insensitive after trimming; partial and fuzzy matching are not used.",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            },
            "example": "Jane Doe"
          },
          {
            "$ref": "#/components/parameters/PersonnelAttendanceScopeQuery"
          },
          {
            "name": "date_start_from",
            "in": "query",
            "required": false,
            "description": "Inclusive event start-date lower bound. Defaults to `2026-01-01` when omitted.",
            "schema": {
              "type": "string",
              "format": "date",
              "default": "2026-01-01"
            },
            "example": "2026-01-01"
          },
          {
            "name": "date_start_to",
            "in": "query",
            "required": false,
            "description": "Inclusive event start-date upper bound. Omit it for no upper bound.",
            "schema": {
              "type": "string",
              "format": "date"
            },
            "example": "2026-12-31"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated events, a paid-feature business error, or a per-user concurrency business error",
            "content": {
              "application/json": {
                "schema": {
                  "oneOf": [
                    {
                      "$ref": "#/components/schemas/PersonnelRelatedEventPage"
                    },
                    {
                      "$ref": "#/components/schemas/FeatureUnavailableBusinessError"
                    },
                    {
                      "$ref": "#/components/schemas/ConcurrencyLimitBusinessError"
                    }
                  ]
                },
                "examples": {
                  "success": {
                    "value": {
                      "items": [
                        {
                          "id": "501",
                          "eventId": "139574",
                          "name": "Retail Technology Expo 2026",
                          "nickname": null,
                          "description": "Retail technology event",
                          "url": "https://example.com/events/retail-technology-expo-2026",
                          "dateStart": "2026-10-01",
                          "dateEnd": "2026-10-03",
                          "venue": "Las Vegas Convention Center",
                          "city": "Las Vegas",
                          "region": "NV",
                          "country": "United States",
                          "exhibitorCount": 950,
                          "hasVisitors": true,
                          "sponsorMatchStarred": 0,
                          "image": null,
                          "dataSource": "Lensmor",
                          "attendance_identity": [
                            "visitor"
                          ]
                        }
                      ],
                      "total": 1,
                      "page": 1,
                      "pageSize": 20,
                      "totalPages": 1,
                      "hasMore": false
                    }
                  },
                  "concurrencyLimitExceeded": {
                    "value": {
                      "code": 429,
                      "message": "Too many concurrent requests for this endpoint",
                      "errorKey": "USER_CONCURRENCY_LIMIT_EXCEEDED",
                      "data": null,
                      "details": null,
                      "traceId": "trace-123"
                    }
                  },
                  "featureUnavailable": {
                    "value": {
                      "code": 400,
                      "message": "This feature is not available to free users, please upgrade to continue",
                      "errorKey": "USER_HAS_NO_FEATURE",
                      "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "403": {
            "description": "Active paid subscription required",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ApiError"
                }
              }
            }
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-codeSamples": [
          {
            "lang": "curl",
            "label": "cURL",
            "source": "curl --request GET \\\n  --url 'https://platform.lensmor.com/external/personnel/events/by-name?person_name=Jane%20Smith&attendance_scope=visitor&page=1&pageSize=20' \\\n  --header 'Authorization: Bearer <token>'"
          }
        ]
      }
    },
    "/external/personnel/unlock-linkedin-activity": {
      "post": {
        "tags": [
          "Personnel"
        ],
        "summary": "Unlock LinkedIn activity",
        "description": "Start LinkedIn activity analysis for personnel records, optionally in an event context.\n\nUse this endpoint after collecting personnel IDs and when the product needs activity metadata rather than contact details. Submit between one and 2,000 personnel IDs. `event_id` is optional; when omitted, the service does not validate that each person belongs to an event. The response reports acceptance, unlock state, task identity, and per-person errors.\n\nThe workflow is asynchronous for newly requested analysis. Do not treat a successful submission as completed analysis; poll or refresh personnel data according to the returned task state. This endpoint does not unlock email addresses or phone numbers.",
        "operationId": "unlockLinkedinActivity",
        "parameters": [
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkedinActivityUnlockRequest"
              },
              "example": {
                "personnel_ids": [
                  "789"
                ],
                "event_id": "139574"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Per-personnel LinkedIn activity unlock result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkedinActivityUnlockResponse"
                },
                "example": {
                  "items": [
                    {
                      "personnel_id": "789",
                      "success": true,
                      "alreadyUnlocked": false,
                      "taskId": null,
                      "error": null
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/contacts/search": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "summary": "Search contacts",
        "description": "Search Lensmor contacts within a required company scope. Start with `company_name`, then add `role`, `person_name`, or both to narrow the results.\n\nUse this endpoint to find people at a target account, confirm coverage before an unlock workflow, and collect personnel IDs for profile, email, phone, or outreach actions.\n\nThis is a read-only, company-scoped discovery endpoint; it does not unlock contact data. Use only the documented filters. No matches return `200 OK` with an empty `items` array. `sourceType` contains non-exclusive labels aggregated across associated events, while `linkedinActivity` and `linkedinActivityStatus` remain `null` here.",
        "operationId": "searchContacts",
        "parameters": [
          {
            "name": "company_name",
            "in": "query",
            "required": true,
            "description": "Required company-name search term that scopes the contact search. Length: 1–200 characters.",
            "example": "Acme",
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 200
            }
          },
          {
            "name": "role",
            "in": "query",
            "description": "Optional job-role or title term used to narrow people within the company. Blank values are ignored.",
            "example": "VP Marketing",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "name": "person_name",
            "in": "query",
            "description": "Optional person-name term used to narrow people within the company. Blank values are ignored.",
            "example": "Jane",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated matching contacts. A valid search with no matches returns the same envelope with an empty `items` array and zero totals.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "101",
                      "fullName": "Jane Doe",
                      "title": "VP Marketing",
                      "department": "marketing",
                      "seniorityLevel": "vp",
                      "linkedinUrl": "https://linkedin.com/in/jane",
                      "companyName": "Acme",
                      "sourceType": [
                        "social",
                        "visitors"
                      ],
                      "email": null,
                      "phone": null,
                      "contactUnlockStatus": "locked",
                      "phoneUnlockStatus": null,
                      "linkedinActivity": null,
                      "linkedinActivityStatus": null,
                      "eventCount": 3
                    }
                  ],
                  "total": 1,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "hasMore": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/contacts/unlock": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "summary": "Unlock contact emails",
        "description": "Submit personnel records for email enrichment, optionally in an event context.\n\nUse this endpoint after contact or personnel discovery when the integration needs email addresses. Newly chargeable work consumes `15` credits per contact and returns `status: accepted` with a task identifier. `event_id` is optional; omitting it skips event membership validation. If every record is already unlocked or skipped, the endpoint can return `status: success` without a task.\n\nOnly poll the email task endpoint when `status` is `accepted` and `task_id` is present. A `201` response means the submission was processed, not that every email was found. Inspect skipped details and item-level results, and avoid duplicate work while an earlier task is active.",
        "operationId": "unlockContactEmails",
        "parameters": [
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "personnel_ids"
                ],
                "properties": {
                  "personnel_ids": {
                    "type": "array",
                    "minItems": 1,
                    "maxItems": 2000,
                    "items": {
                      "type": "string"
                    },
                    "description": "Lensmor personnel identifiers selected for this batch operation.",
                    "example": [
                      "789"
                    ]
                  },
                  "event_id": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 100,
                    "description": "Optional Lensmor event identifier returned as `id` or `eventId`. When omitted, event membership validation is skipped.",
                    "example": "26855"
                  }
                }
              },
              "example": {
                "personnel_ids": [
                  "789",
                  "790"
                ],
                "event_id": "139574"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Unlock submission accepted, or completed with no chargeable work",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactUnlockSubmission"
                },
                "example": {
                  "status": "accepted",
                  "task_id": "321",
                  "job_id": "321"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/contacts/unlock-tasks/{taskId}": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "summary": "Get contact unlock task",
        "description": "Poll an email-unlock task created by the contact email submission endpoint.\n\nStore the returned `task_id` and use it here to make the workflow resumable across background jobs, frontend refreshes, or retries. Continue polling while `taskStatus` is `pending` or `processing`, then stop when it reaches `completed` or `failed`. Use a controlled polling interval and treat each read as a status check, not a new unlock request.\n\nTask completion does not guarantee an email for every submitted person. Process item-level status, email, and error information independently, persist successful results, and do not retry the same task after it reaches a terminal state.",
        "operationId": "getContactUnlockTask",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            },
            "description": "Email-unlock task identifier returned as `task_id` by the submission endpoint.",
            "example": "321"
          }
        ],
        "responses": {
          "200": {
            "description": "Unlock task status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactUnlockTask"
                },
                "example": {
                  "taskId": "321",
                  "taskStatus": "processing",
                  "items": [
                    {
                      "personnelId": "789",
                      "status": "unlocked",
                      "email": "jane@acme.example"
                    },
                    {
                      "personnelId": "790",
                      "status": "processing"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/profile-matching/actions/apply-recommended-events/paged": {
      "post": {
        "tags": [
          "Profile Matching"
        ],
        "summary": "Apply profile and get recommended events",
        "description": "Apply company-profile inputs synchronously and return a paginated set of Lensmor events ranked for that profile.\n\nUse this endpoint when discovery starts from a company website or target-audience description rather than from a known event. Provide at least one of `company_url` or `target_audience`, then optionally narrow results by geography, category, event type, dates, future status, or attendee-count range.\n\nThis endpoint does not spend credits or unlock event access. Recommendation scores, tiers, reasons, and matched-exhibitor evidence are point-in-time outputs that can change as the profile or Lensmor data changes. Use neutral event list search when profile-based ranking is not required.",
        "operationId": "applyRecommendedEventsPaged",
        "requestBody": {
          "$ref": "#/components/requestBodies/ProfileMatchingBody"
        },
        "responses": {
          "201": {
            "description": "Recommended events",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProfileEventRecommendationPage"
                },
                "example": {
                  "status": "completed",
                  "items": [
                    {
                      "id": "501",
                      "eventId": "10067",
                      "name": "American Banker Digital Banking 2026",
                      "city": "Orlando",
                      "country": "United States",
                      "attendeeCount": 1825,
                      "declaredExpectedAttendees": 600,
                      "sourceTags": [],
                      "dataSource": "Lensmor",
                      "matched_exhibitor_count": 19,
                      "matched_personnel_count": 85,
                      "match_score": 0.84,
                      "unlocked": false,
                      "relevanceReason": null,
                      "rank": 1
                    }
                  ],
                  "total": 42,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 3,
                  "hasMore": true,
                  "condition_tags": {},
                  "profile_version": 12,
                  "active_result_version": 12,
                  "is_stale": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/profile-matching/recommendations/exhibitors": {
      "get": {
        "tags": [
          "Profile Matching"
        ],
        "summary": "Get recommended exhibitors for event",
        "description": "Return exhibitor recommendation state for one selected event under the authenticated user's current profile.\n\nUse this endpoint when the workflow needs profile-aware exhibitor prioritization rather than the neutral event exhibitor catalog. Filters can narrow the recommendation page by location, company text or exact name, category, industry, and employee-count range.\n\nDepending on recommendation readiness, items can contain ranked match evidence or an unranked fallback state. Inspect `recommendationProcessing`, `isRecommended`, rank, status, score, tier, and reason instead of assuming every result is fully scored. Use the standard exhibitor list when preview/full event-access semantics are the primary requirement.",
        "operationId": "getRecommendedExhibitors",
        "parameters": [
          {
            "$ref": "#/components/parameters/EventIdQuery"
          },
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "name": "location",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by one or more country or region labels. Repeat the query parameter for multiple values.",
            "example": [
              "United States"
            ]
          },
          {
            "name": "searchQuery",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Search company names or descriptions within the event recommendation set.",
            "example": "analytics"
          },
          {
            "name": "exhibitorName",
            "in": "query",
            "schema": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "description": "Filter by one or more exact exhibitor company names.",
            "example": [
              "Acme"
            ]
          },
          {
            "$ref": "#/components/parameters/CategoryArray"
          },
          {
            "$ref": "#/components/parameters/IndustryArray"
          },
          {
            "name": "employeesMin",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Minimum company employee count, inclusive.",
            "example": 50
          },
          {
            "name": "employeesMax",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 0
            },
            "description": "Maximum company employee count, inclusive.",
            "example": 1000
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated recommendation state or unranked fallback exhibitor rows",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RecommendedExhibitorPage"
                },
                "example": {
                  "items": [
                    {
                      "id": "456",
                      "companyName": "Acme Retail Systems",
                      "isRecommended": true,
                      "recommendationRank": 1,
                      "matchStatus": "ready",
                      "matchScore": 91,
                      "matchTier": "top_match",
                      "reason": "Strong fit for the active profile."
                    }
                  ],
                  "total": 87,
                  "page": 1,
                  "pageSize": 20,
                  "totalPages": 5,
                  "hasMore": true,
                  "recommendationProcessing": false
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/contacts/unlock-phone": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "summary": "Unlock contact phone numbers",
        "description": "Submit personnel records for phone-number enrichment, optionally in an event context.\n\nUse this endpoint after contact or personnel discovery when the integration needs phone numbers. Newly chargeable work consumes `150` credits per contact and returns `status: accepted` with a task identifier. `event_id` is optional; omitting it skips event membership validation. When there is no chargeable work, the endpoint can return `status: success` without a task.\n\nOnly poll the phone task endpoint when `status` is `accepted` and `task_id` is present. A `201` response does not guarantee that every phone number will be found. Inspect skipped details and item-level failures, and avoid duplicate submissions while a task is pending or processing.",
        "operationId": "unlockContactPhones",
        "parameters": [
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/PhoneUnlockRequest"
              },
              "example": {
                "personnel_ids": [
                  "789"
                ],
                "event_id": "139574"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Phone unlock submission accepted, or completed with no chargeable work",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactUnlockSubmission"
                },
                "example": {
                  "status": "accepted",
                  "task_id": "321",
                  "job_id": "321"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "402": {
            "$ref": "#/components/responses/PaymentRequired"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/contacts/unlock-phone-tasks/{taskId}": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "summary": "Get phone unlock task",
        "description": "Poll a phone-unlock task created by the contact phone submission endpoint.\n\nStore the returned `task_id` so the workflow can resume across background jobs, frontend refreshes, or retries. Poll while `taskStatus` is `pending` or `processing`, then stop when it reaches `completed` or `failed`. Use a controlled interval and treat each read as a status check, not a new unlock request.\n\nTask-level completion does not guarantee a phone number for every person. Handle item-level status, phone, and `errorCode` independently, persist successful results, surface per-record failures, and do not retry a terminal task.",
        "operationId": "getPhoneUnlockTask",
        "parameters": [
          {
            "name": "taskId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string",
              "pattern": "^[0-9]+$"
            },
            "description": "Phone-unlock task identifier returned as `task_id` by the submission endpoint.",
            "example": "321"
          }
        ],
        "responses": {
          "200": {
            "description": "Phone unlock task status",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneUnlockTask"
                },
                "example": {
                  "taskId": "321",
                  "taskStatus": "completed",
                  "items": [
                    {
                      "personnelId": "789",
                      "status": "unlocked",
                      "phone": "+1 415 555 0100"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/personnel/generate-outreach-message": {
      "post": {
        "tags": [
          "Personnel"
        ],
        "summary": "Generate outreach messages",
        "description": "Start asynchronous AI outreach generation for one or more personnel records, with optional event context.\n\nUse this endpoint after personnel selection when the integration needs personalized email or LinkedIn copy. Submit up to 2,000 personnel IDs, choose `email`, `linkedin_message`, or both, and optionally provide `event_id`, LinkedIn variants (`inmail`, `connection_note`, `connected_message`), and an outreach purpose. The operation does not deduct credits.\n\nEach personnel item can succeed or fail independently and may create background work. Store returned task identifiers and retrieve the latest generated content with the outreach detail endpoint. Generating content does not send or contact the person.",
        "operationId": "generateOutreachMessage",
        "parameters": [
          {
            "$ref": "#/components/parameters/CallSource"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OutreachMessageRequest"
              },
              "example": {
                "personnel_ids": [
                  "789"
                ],
                "event_id": "501",
                "channels": [
                  "email",
                  "linkedin_message"
                ],
                "linkedin_message_types": [
                  "inmail",
                  "connection_note"
                ],
                "outreach_purpose": "Book a product demo"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Outreach message generation accepted",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutreachMessageResponse"
                },
                "example": {
                  "items": [
                    {
                      "personnel_id": "789",
                      "success": true,
                      "taskId": null,
                      "error": null
                    }
                  ],
                  "taskCenterId": "321"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/external/personnel/outreach": {
      "get": {
        "tags": [
          "Personnel"
        ],
        "summary": "Get outreach message detail",
        "description": "Retrieve the most recent AI-generated outreach result for one personnel and event combination.\n\nUse this endpoint after submitting outreach generation, or before regenerating, to check whether content already exists. The response can include email content and separate LinkedIn variants such as InMail, connection note, and connected-message copy, together with source, purpose, tone, status, and timestamps when available.\n\n`found: false` is a valid lookup result when content has not been generated, is not ready, or the event cannot be resolved. Malformed numeric identifiers return `400`. This endpoint only retrieves draft content; it does not send messages. Regenerating the same personnel-and-event combination can replace the previous result.",
        "operationId": "getOutreachDetail",
        "parameters": [
          {
            "name": "personnel_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 20
            },
            "description": "Personnel identifier used in the outreach generation request.",
            "example": "789"
          },
          {
            "name": "event_id",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string",
              "minLength": 1,
              "maxLength": 20
            },
            "description": "Event identifier used in the outreach generation request.",
            "example": "139574"
          }
        ],
        "responses": {
          "200": {
            "description": "Outreach message detail",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutreachDetail"
                },
                "example": {
                  "found": true,
                  "channels": [
                    "email",
                    "linkedin_message"
                  ],
                  "messages": {
                    "email": "Hi Jane, I would like to compare notes before Retail Technology Expo.",
                    "linkedin_message": "Hi Jane, are you open to a quick conversation before the event?",
                    "linkedin": {
                      "inmail": {
                        "subject": "Retail Technology Expo",
                        "body": "Hi Jane, I would like to compare notes before the event."
                      },
                      "connection_note": {
                        "body": "Hi Jane, would be glad to connect before the event."
                      }
                    }
                  },
                  "outreach_purpose": "Book a product demo",
                  "tone": "professional",
                  "status": "ready"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "Business sk API key",
        "description": "Send the full Business API key from Settings -> API Keys, for example `Authorization: Bearer sk_your_api_key`."
      }
    },
    "parameters": {
      "Page": {
        "name": "page",
        "in": "query",
        "description": "One-based page number. Use `1` for the first page and increment it while `hasMore` is `true`.",
        "example": 1,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "PageSize": {
        "name": "pageSize",
        "in": "query",
        "description": "Maximum number of records requested per page. The shared default is `20` and the shared upper limit is `100`; individual endpoints can document a lower maximum.",
        "example": 20,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "EventIdQuery": {
        "name": "event_id",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "description": "Lensmor event identifier returned as `id` or `eventId` by event responses.",
        "example": "26855"
      },
      "EventIdPath": {
        "name": "id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100
        },
        "description": "Lensmor event identifier returned as `id` or `eventId` by event responses.",
        "example": "26855"
      },
      "ExhibitorIdQuery": {
        "name": "exhibitor_id",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1
        },
        "description": "Lensmor exhibitor identifier returned by exhibitor list, search, or recommendation results.",
        "example": "4182"
      },
      "PersonnelIdQuery": {
        "name": "personnel_id",
        "in": "query",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 20
        },
        "description": "Lensmor personnel identifier returned by personnel or contact results.",
        "example": "789"
      },
      "CategoryArray": {
        "name": "category",
        "in": "query",
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "description": "Filter by one or more category labels. Repeat the query parameter for multiple values.",
        "example": [
          "Technology"
        ]
      },
      "IndustryArray": {
        "name": "industry",
        "in": "query",
        "schema": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "description": "Filter by one or more industry labels. Repeat the query parameter for multiple values.",
        "example": [
          "Software"
        ]
      },
      "CallSource": {
        "name": "x-call-source",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "enum": [
            "api",
            "agent"
          ]
        },
        "description": "Identify the caller as `api` or `agent` for usage attribution. Defaults to `api` when omitted.",
        "example": "api"
      },
      "CompanyAttendanceScopeQuery": {
        "name": "attendance_scope",
        "in": "query",
        "required": false,
        "description": "Filter events by this company's attendance identity. Defaults to `all`. `exhibitor` includes events with exhibitor evidence, including events that also have visitor evidence. `visitor` returns visitor-only events and excludes events with exhibitor evidence. Only `all`, `exhibitor`, and `visitor` are valid; other values, including `null`, return 400.",
        "schema": {
          "type": "string",
          "enum": [
            "all",
            "exhibitor",
            "visitor"
          ],
          "default": "all"
        },
        "example": "visitor"
      },
      "PersonnelAttendanceScopeQuery": {
        "name": "attendance_scope",
        "in": "query",
        "required": false,
        "description": "Filter events by attendance identities for the matched person or people. Defaults to `all`. `exhibitor_employee` includes events with exhibitor-employee evidence, including events that also have visitor evidence. `visitor` returns visitor-only events and excludes events with exhibitor-employee evidence. Exact-name lookups combine evidence per event across matched personnel before applying this filter. Only `all`, `exhibitor_employee`, and `visitor` are valid; other values, including `null`, return 400.",
        "schema": {
          "type": "string",
          "enum": [
            "all",
            "exhibitor_employee",
            "visitor"
          ],
          "default": "all"
        },
        "example": "visitor"
      }
    },
    "requestBodies": {
      "EventIdBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "event_id"
              ],
              "properties": {
                "event_id": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 100,
                  "description": "Lensmor event identifier returned as `id` or `eventId` by event responses.",
                  "example": "26855"
                }
              }
            },
            "example": {
              "event_id": "139574"
            }
          }
        },
        "description": "Select the event to score or otherwise process."
      },
      "ExhibitorSearchBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "company_url": {
                  "type": "string",
                  "format": "uri",
                  "description": "Public `http(s)` company website used as profile context. Provide it or `target_audience`.",
                  "example": "https://acme.example"
                },
                "target_audience": {
                  "type": "string",
                  "description": "Free-form ideal-customer or target-audience description. Provide it or `company_url`.",
                  "example": "Enterprise marketing teams in North America"
                },
                "page": {
                  "type": "integer",
                  "minimum": 1,
                  "default": 1,
                  "description": "One-based result page number.",
                  "example": 1
                },
                "pageSize": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100,
                  "default": 20,
                  "description": "Maximum records requested per page; defaults to `20` and cannot exceed `100`.",
                  "example": 20
                }
              },
              "anyOf": [
                {
                  "required": [
                    "company_url"
                  ]
                },
                {
                  "required": [
                    "target_audience"
                  ]
                }
              ]
            },
            "example": {
              "company_url": "https://acme.example",
              "page": 1,
              "pageSize": 20
            }
          }
        },
        "description": "Provide company-profile context and pagination for contextual exhibitor matching."
      },
      "CompanyNameBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "company_name"
              ],
              "properties": {
                "company_name": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Company-name search term. Matching is precision-first for company-name endpoints.",
                  "example": "Acme"
                },
                "page": {
                  "type": "integer",
                  "minimum": 1,
                  "default": 1,
                  "description": "One-based result page number.",
                  "example": 1
                },
                "pageSize": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100,
                  "default": 20,
                  "description": "Maximum records requested per page; defaults to `20` and cannot exceed `100`.",
                  "example": 20
                }
              }
            },
            "example": {
              "company_name": "Acme",
              "page": 1,
              "pageSize": 20
            }
          }
        },
        "description": "Provide the required company name and pagination for precision-first exhibitor lookup."
      },
      "SearchEventsByCompanyNameBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "required": [
                "company_name"
              ],
              "properties": {
                "company_name": {
                  "type": "string",
                  "minLength": 1,
                  "maxLength": 200,
                  "description": "Company-name search term. Matching is precision-first for company-name endpoints.",
                  "example": "Acme"
                },
                "sponsor_match_starred": {
                  "type": "integer",
                  "enum": [
                    0,
                    1
                  ],
                  "description": "Use `1` for starred Sponsor Match events or `0` for non-starred events; omit it to include both.",
                  "example": 1
                },
                "page": {
                  "type": "integer",
                  "minimum": 1,
                  "default": 1,
                  "description": "One-based result page number.",
                  "example": 1
                },
                "pageSize": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100,
                  "default": 20,
                  "description": "Maximum records requested per page; defaults to `20` and cannot exceed `100`.",
                  "example": 20
                },
                "attendance_scope": {
                  "type": "string",
                  "enum": [
                    "all",
                    "exhibitor",
                    "visitor"
                  ],
                  "default": "all",
                  "description": "Filter events by this company's attendance identity. Defaults to `all`. `exhibitor` includes events with exhibitor evidence, including events that also have visitor evidence. `visitor` returns visitor-only events and excludes events with exhibitor evidence. Only `all`, `exhibitor`, and `visitor` are valid; other values, including `null`, return 400.",
                  "example": "exhibitor"
                }
              }
            },
            "example": {
              "company_name": "Acme",
              "sponsor_match_starred": 1,
              "page": 1,
              "pageSize": 20,
              "attendance_scope": "exhibitor"
            }
          }
        },
        "description": "Provide the company name, optional Sponsor Match filter, and pagination for event reverse search. Optional `attendance_scope` filters by company attendance identity and defaults to `all`."
      },
      "ProfileMatchingBody": {
        "required": true,
        "content": {
          "application/json": {
            "schema": {
              "type": "object",
              "properties": {
                "company_url": {
                  "type": "string",
                  "format": "uri",
                  "description": "Public `http(s)` company website used as profile context. Provide it or `target_audience`.",
                  "example": "https://acme.example",
                  "maxLength": 500
                },
                "target_audience": {
                  "type": "string",
                  "description": "Free-form ideal-customer or target-audience description. Provide it or `company_url`.",
                  "example": "Enterprise marketing teams in North America"
                },
                "page": {
                  "type": "integer",
                  "minimum": 1,
                  "default": 1,
                  "description": "One-based result page number.",
                  "example": 1
                },
                "pageSize": {
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 100,
                  "default": 20,
                  "description": "Maximum records requested per page; defaults to `20` and cannot exceed `100`.",
                  "example": 20
                },
                "autoRecommendTop3EventsEnabled": {
                  "type": "boolean",
                  "description": "Override synchronous top-three recommendation-reason generation for this request.",
                  "example": true
                },
                "city": {
                  "type": "string",
                  "description": "Filter recommendations by city.",
                  "example": "Las Vegas"
                },
                "region": {
                  "type": "string",
                  "description": "Filter recommendations by region or state.",
                  "example": "Nevada"
                },
                "country": {
                  "type": "string",
                  "description": "Filter recommendations by country.",
                  "example": "United States"
                },
                "category": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Filter by category labels. Arrays and comma-separated inputs are normalized.",
                  "example": [
                    "Technology"
                  ]
                },
                "eventTypeIds": {
                  "type": "array",
                  "items": {
                    "type": "integer"
                  },
                  "description": "Filter by Lensmor event-type identifiers.",
                  "example": [
                    1
                  ]
                },
                "dateStartFrom": {
                  "type": "string",
                  "format": "date",
                  "description": "Inclusive lower bound for event start date in `YYYY-MM-DD` format.",
                  "example": "2025-01-01"
                },
                "dateStartTo": {
                  "type": "string",
                  "format": "date",
                  "description": "Inclusive upper bound for event start date in `YYYY-MM-DD` format.",
                  "example": "2025-12-31"
                },
                "future": {
                  "type": "integer",
                  "description": "Future-event flag used by the recommendation filter.",
                  "example": 1
                },
                "attendeeCountMin": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Minimum attendee count, inclusive.",
                  "example": 500
                },
                "attendeeCountMax": {
                  "type": "integer",
                  "minimum": 0,
                  "description": "Maximum attendee count, inclusive.",
                  "example": 50000
                },
                "linkedin_url": {
                  "type": "string",
                  "format": "uri",
                  "maxLength": 500,
                  "description": "Optional safe public LinkedIn profile URL used as additional profile context.",
                  "example": "https://www.linkedin.com/in/jane-doe"
                },
                "company_description": {
                  "type": "string",
                  "maxLength": 2000,
                  "description": "Optional company description used as additional profile-matching context.",
                  "example": "We help retailers connect with technology vendors through trade shows and events."
                },
                "industry": {
                  "type": "string",
                  "maxLength": 255,
                  "description": "Optional company industry used as profile context.",
                  "example": "Retail Technology"
                },
                "target_industry": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "description": "Optional target industries used to scope exhibitor recommendations.",
                  "example": [
                    "Artificial Intelligence",
                    "Technology & Software"
                  ]
                },
                "planned_events": {
                  "type": "string",
                  "maxLength": 500,
                  "description": "Optional free-text description of events the caller already plans to attend.",
                  "example": "NRF, Shoptalk, and regional retail trade shows"
                },
                "target_management_level": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "description": "Optional management-level labels used for personnel matching.",
                  "example": [
                    "C-Level",
                    "VP"
                  ]
                },
                "target_job_titles": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "maxLength": 255
                  },
                  "description": "Optional job-title or function terms. The runtime normalizes the input and retains the first five non-empty values.",
                  "example": [
                    "marketing",
                    "ecommerce",
                    "VP Marketing"
                  ]
                },
                "timeout_ms": {
                  "type": "integer",
                  "minimum": 60000,
                  "maximum": 3600000,
                  "description": "Optional synchronous processing timeout in milliseconds, from one minute to one hour.",
                  "example": 900000
                }
              },
              "anyOf": [
                {
                  "required": [
                    "company_url"
                  ]
                },
                {
                  "required": [
                    "target_audience"
                  ]
                }
              ]
            },
            "example": {
              "company_url": "https://acme.example",
              "page": 1,
              "pageSize": 20,
              "country": "United States",
              "future": 1
            }
          }
        },
        "description": "Provide company-profile context, pagination, and optional event filters for recommendation generation."
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Bad request",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 400,
              "message": "Invalid request",
              "errorKey": "INVALID_REQUEST",
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing or invalid API key",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 401,
              "message": "Invalid API key",
              "errorKey": "INVALID_API_KEY",
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      },
      "PaymentRequired": {
        "description": "Insufficient credits",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 402,
              "message": "Insufficient credits",
              "errorKey": "INSUFFICIENT_CREDITS",
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      },
      "NotFound": {
        "description": "Resource not found",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 404,
              "message": "Resource not found",
              "errorKey": "NOT_FOUND",
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      },
      "Conflict": {
        "description": "Business conflict",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 409,
              "message": "Request conflicts with the current resource state",
              "errorKey": "STATE_CONFLICT",
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "Selected personnel batch exceeds the runtime limit",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 422,
              "message": "Selected leads limit exceeded: requested 2001, limit 2000",
              "errorKey": "LEAD_SELECTION_LIMIT_EXCEEDED",
              "details": {
                "requestedCount": 2001,
                "limit": 2000,
                "selectionMode": "selected"
              },
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            },
            "example": {
              "code": 429,
              "message": "Rate limit exceeded",
              "errorKey": "RATE_LIMIT_EXCEEDED",
              "traceId": "2be6d7f4-3b2d-4d11-8e2d-7a2e4c3e9a10"
            }
          }
        }
      }
    },
    "schemas": {
      "ApiError": {
        "type": "object",
        "required": [
          "code",
          "message",
          "errorKey",
          "traceId"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "description": "Numeric or symbolic code that identifies the response or business condition."
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation suitable for logs or user-facing error handling."
          },
          "errorKey": {
            "type": "string",
            "description": "Stable machine-readable error key for branching and analytics."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier to include in support or incident reports."
          },
          "details": {
            "description": "Optional structured business or validation context. Omitted when the error has no additional details."
          }
        },
        "description": "Shared error envelope returned by public Lensmor API endpoints."
      },
      "ConcurrencyLimitBusinessError": {
        "type": "object",
        "required": [
          "code",
          "message",
          "errorKey",
          "data",
          "details",
          "traceId"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "const": 429,
            "description": "Numeric or symbolic code that identifies the response or business condition."
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation suitable for logs or user-facing error handling."
          },
          "errorKey": {
            "type": "string",
            "const": "USER_CONCURRENCY_LIMIT_EXCEEDED",
            "description": "Stable machine-readable error key for branching and analytics."
          },
          "data": {
            "type": "null",
            "description": "Optional structured business-error data; `null` when no extra data is available."
          },
          "details": {
            "type": "null",
            "description": "Optional structured error details; `null` when no extra details are available."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier to include in support or incident reports."
          }
        },
        "additionalProperties": false,
        "description": "Business error returned when a user exceeds the endpoint's concurrent-request limit."
      },
      "CreditBalance": {
        "type": "object",
        "required": [
          "totalAmount",
          "totalBalance",
          "subscriptionAmount",
          "subscriptionBalance",
          "addonAmount",
          "addonBalance",
          "addonExpireAt",
          "giftAmount",
          "giftBalance",
          "resetAt"
        ],
        "properties": {
          "totalAmount": {
            "type": "number",
            "description": "Total credits allocated across subscription, add-on, and gift buckets."
          },
          "totalBalance": {
            "type": "number",
            "description": "Total credits currently available to spend across all buckets."
          },
          "subscriptionAmount": {
            "type": "number",
            "description": "Credits allocated by the current subscription period."
          },
          "subscriptionBalance": {
            "type": "number",
            "description": "Subscription credits currently available to spend."
          },
          "addonAmount": {
            "type": "number",
            "description": "Total credits allocated through add-on purchases."
          },
          "addonBalance": {
            "type": "number",
            "description": "Add-on credits currently available to spend."
          },
          "addonExpireAt": {
            "type": [
              "number",
              "null"
            ],
            "description": "Unix timestamp for add-on credit expiry, or `null` when no expiry applies."
          },
          "giftAmount": {
            "type": "number",
            "description": "Total promotional or gifted credits allocated."
          },
          "giftBalance": {
            "type": "number",
            "description": "Promotional or gifted credits currently available to spend."
          },
          "resetAt": {
            "type": [
              "number",
              "null"
            ],
            "description": "Unix timestamp for the next subscription-credit reset, or `null` when unavailable."
          }
        },
        "description": "Current total and per-bucket Lensmor credit amounts for the API key owner."
      },
      "EventItem": {
        "type": "object",
        "required": [
          "id",
          "eventId",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable Lensmor identifier for this record."
          },
          "eventId": {
            "type": "string",
            "description": "Public event identifier accepted by event-scoped endpoints."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Display name when available."
          },
          "nickname": {
            "type": [
              "string",
              "null"
            ],
            "description": "Alternative or shortened event name when available."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Public description when available."
          },
          "url": {
            "type": [
              "string",
              "null"
            ],
            "description": "Canonical public website URL when available."
          },
          "dateStart": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Event start date in ISO `YYYY-MM-DD` format when available."
          },
          "dateEnd": {
            "type": [
              "string",
              "null"
            ],
            "format": "date",
            "description": "Event end date in ISO `YYYY-MM-DD` format when available."
          },
          "venue": {
            "type": [
              "string",
              "null"
            ],
            "description": "Event venue name when available."
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "description": "City associated with the record when available."
          },
          "region": {
            "type": [
              "string",
              "null"
            ],
            "description": "Region, state, or province when available."
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "description": "Country associated with the record when available."
          },
          "exhibitorCount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Known exhibitor count for the event when available."
          },
          "hasVisitors": {
            "type": "boolean",
            "description": "True when the event currently has registered Visitor data available. This is an availability signal, not proof that the caller has unlocked Visitor access."
          },
          "sponsorMatchStarred": {
            "type": "integer",
            "enum": [
              0,
              1
            ],
            "description": "Sponsor Match starred state returned by Lensmor."
          },
          "image": {
            "type": [
              "string",
              "null"
            ],
            "description": "Public image or logo URL when available."
          },
          "dataSource": {
            "type": "string",
            "const": "Lensmor",
            "description": "Source label for the returned Lensmor record."
          }
        },
        "additionalProperties": true,
        "description": "Shared public event summary used by event lists, search results, and recommendation workflows."
      },
      "EventDetail": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventItem"
          },
          {
            "type": "object",
            "properties": {
              "latitude": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Latitude returned as part of this event detail object."
              },
              "longitude": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Longitude returned as part of this event detail object."
              },
              "attendeeCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Attendee Count returned as part of this event detail object."
              },
              "priceLower": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Price Lower returned as part of this event detail object."
              },
              "priceUpper": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Price Upper returned as part of this event detail object."
              },
              "eventType": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Event Type returned as part of this event detail object."
              },
              "categories": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                },
                "description": "Category labels associated with the company or event."
              },
              "topics": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Topics returned as part of this event detail object."
              },
              "topicsCount": {
                "type": "integer",
                "description": "Topics Count returned as part of this event detail object."
              },
              "verified": {
                "type": "integer",
                "description": "Verified returned as part of this event detail object."
              },
              "future": {
                "type": "integer",
                "description": "Future returned as part of this event detail object."
              },
              "historic": {
                "type": "integer",
                "description": "Historic returned as part of this event detail object."
              },
              "historicEvent": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Historic Event returned as part of this event detail object."
              },
              "personnelCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Personnel Count returned as part of this event detail object."
              },
              "eventTypes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": true
                },
                "description": "Event Types returned as part of this event detail object."
              }
            }
          }
        ],
        "description": "Detailed event response that extends the shared event summary."
      },
      "EventPage": {
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventItem"
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "total": {
            "type": "integer",
            "description": "Total matching records across all pages."
          },
          "page": {
            "type": "integer",
            "description": "One-based page number returned."
          },
          "pageSize": {
            "type": "integer",
            "description": "Maximum records requested for this page."
          },
          "totalPages": {
            "type": "integer",
            "description": "Total pages available for the current query."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another result page is available."
          }
        },
        "additionalProperties": true,
        "description": "Standard paginated collection of public event summaries."
      },
      "MatchedExhibitorSummary": {
        "type": "object",
        "required": [
          "id",
          "companyName"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable Lensmor identifier for this record."
          },
          "companyName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company display name when available."
          }
        },
        "description": "Compact exhibitor identity explaining an event-company match."
      },
      "EventReverseSearchItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventItem"
          },
          {
            "type": "object",
            "required": [
              "matchedExhibitors",
              "attendance_identity"
            ],
            "properties": {
              "matchedExhibitors": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/MatchedExhibitorSummary"
                },
                "description": "Admitted company matches with exhibitor relationships at this event. This array can be empty for visitor-only results."
              },
              "attendance_identity": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "exhibitor",
                    "visitor"
                  ]
                },
                "description": "Complete attendance identities for this company at this event. An event matched by a scope still returns its complete identity array.",
                "example": [
                  "exhibitor",
                  "visitor"
                ]
              }
            }
          }
        ],
        "description": "Event result with the company's attendance identities and any matched exhibitor relationships. Visitor-only results can have an empty matchedExhibitors array."
      },
      "EventReverseSearchPage": {
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/EventReverseSearchItem"
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "total": {
            "type": "integer",
            "description": "Total matching records across all pages."
          },
          "page": {
            "type": "integer",
            "description": "One-based page number returned."
          },
          "pageSize": {
            "type": "integer",
            "description": "Maximum records requested for this page."
          },
          "totalPages": {
            "type": "integer",
            "description": "Total pages available for the current query."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another result page is available."
          }
        },
        "description": "Paginated events returned by exhibitor company-name reverse search."
      },
      "EventFitScore": {
        "type": "object",
        "required": [
          "event",
          "score",
          "recommendation",
          "breakdown"
        ],
        "properties": {
          "event": {
            "$ref": "#/components/schemas/EventItem",
            "description": "Event record associated with this result."
          },
          "score": {
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "description": "Overall event fit score on a 0-10 scale."
          },
          "recommendation": {
            "type": "string",
            "enum": [
              "recommended",
              "consider",
              "not_recommended"
            ],
            "description": "Decision category derived from score: recommended for 7-10, consider for 4 to below 7, and not_recommended for below 4."
          },
          "breakdown": {
            "type": "object",
            "required": [
              "profile_match",
              "matched_exhibitor_density",
              "event_scale"
            ],
            "properties": {
              "profile_match": {
                "type": "number",
                "minimum": 0,
                "maximum": 10,
                "description": "Profile-context compatibility component on a 0-10 scale."
              },
              "matched_exhibitor_density": {
                "type": "number",
                "minimum": 0,
                "maximum": 10,
                "description": "Matched-exhibitor density component on a 0-10 scale. This is not verified buyer or attendee density."
              },
              "event_scale": {
                "type": "number",
                "minimum": 0,
                "maximum": 10,
                "description": "Event-scale component derived from the Lensmor exhibitor count and capped at 10."
              }
            },
            "additionalProperties": false,
            "description": "Structured explanation of factors contributing to the fit score."
          }
        },
        "description": "Profile-dependent fit assessment for one event."
      },
      "RecommendedExhibitorItem": {
        "type": "object",
        "required": [
          "id",
          "companyName",
          "isRecommended"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable Lensmor identifier for this record."
          },
          "companyName": {
            "type": "string",
            "description": "Company display name when available."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Public description when available."
          },
          "logo": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company logo URL when available."
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company website URL when available."
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "description": "Country associated with the record when available."
          },
          "industry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized company industry when available."
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Category labels associated with the company or event."
          },
          "employeeCount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Known company employee count when available."
          },
          "companySize": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized company-size band when available."
          },
          "fundingRound": {
            "type": [
              "string",
              "null"
            ],
            "description": "Latest known funding-round label when available."
          },
          "techStacks": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Known technology-stack labels associated with the company."
          },
          "isRecommended": {
            "type": "boolean",
            "description": "True only when the item belongs to the active recommendation snapshot."
          },
          "recommendationRank": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 1,
            "description": "One-based recommendation rank when scoring is ready."
          },
          "matchStatus": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pending_unlock",
              "processing",
              "ready",
              "failed",
              null
            ],
            "description": "Current recommendation or matching processing state."
          },
          "matchScore": {
            "type": [
              "number",
              "null"
            ],
            "description": "Numeric profile-match score when available."
          },
          "matchTier": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "top_match",
              "strong_match",
              "qualifying_match",
              null
            ],
            "description": "Normalized match tier when available."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Recommendation reason when matchStatus is ready. The field name is reason, not matchReason."
          }
        },
        "additionalProperties": true,
        "description": "Exhibitor company plus recommendation readiness and match evidence."
      },
      "RecommendedExhibitorPage": {
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore",
          "recommendationProcessing"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RecommendedExhibitorItem"
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Total matching records across all pages."
          },
          "page": {
            "type": "integer",
            "minimum": 1,
            "description": "One-based page number returned."
          },
          "pageSize": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100,
            "description": "Maximum records requested for this page."
          },
          "totalPages": {
            "type": "integer",
            "minimum": 0,
            "description": "Total pages available for the current query."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another result page is available."
          },
          "recommendationProcessing": {
            "type": "boolean",
            "description": "True when recommendation detail generation is still processing for the event."
          },
          "code": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "AI_SEARCH_RESULT_MISMATCH",
              null
            ],
            "description": "Present on unranked fallback results."
          },
          "show_refresh_hint": {
            "type": "boolean",
            "description": "Present on fallback results. This flag does not identify the cause or prescribe a required action."
          }
        },
        "additionalProperties": true,
        "description": "Paginated exhibitor recommendation state for one event."
      },
      "EventRankItem": {
        "type": "object",
        "required": [
          "event_id",
          "name",
          "rank",
          "match_score",
          "reasons"
        ],
        "properties": {
          "event_id": {
            "type": "string",
            "description": "Lensmor event identifier associated with this record or action."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Display name when available."
          },
          "rank": {
            "type": "integer",
            "description": "One-based rank within the supplied candidate set."
          },
          "match_score": {
            "type": "number",
            "description": "Numeric match score used to order the ranked result."
          },
          "reasons": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Human-readable reasons supporting the rank."
          }
        },
        "description": "One ranked event and its profile-match evidence."
      },
      "EventUnlockResult": {
        "type": "object",
        "required": [
          "success",
          "alreadyUnlocked",
          "creditsUsed",
          "balanceAfter",
          "event"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether this operation or item completed successfully."
          },
          "alreadyUnlocked": {
            "type": "boolean",
            "description": "Whether the requested access was already available before this call."
          },
          "creditsUsed": {
            "type": "number",
            "description": "Credits consumed by this operation."
          },
          "balanceAfter": {
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "subscriptionBalance",
                  "permanentBalance",
                  "totalBalance",
                  "unlimited"
                ],
                "properties": {
                  "subscriptionBalance": {
                    "type": "number",
                    "description": "Subscription credits currently available to spend."
                  },
                  "permanentBalance": {
                    "type": "number",
                    "description": "Permanent Balance returned as part of this event unlock result object."
                  },
                  "totalBalance": {
                    "type": "number",
                    "description": "Total credits currently available to spend across all buckets."
                  },
                  "unlimited": {
                    "type": "boolean",
                    "description": "Unlimited returned as part of this event unlock result object."
                  }
                },
                "additionalProperties": true
              },
              {
                "type": "null"
              }
            ],
            "description": "Credit balance remaining after the operation."
          },
          "event": {
            "type": "object",
            "required": [
              "id",
              "eventId",
              "name"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Stable Lensmor identifier for this record."
              },
              "eventId": {
                "type": "string",
                "description": "Public event identifier accepted by event-scoped endpoints."
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Display name when available."
              }
            },
            "description": "Event record associated with this result."
          }
        },
        "description": "Result of requesting the base event access layer."
      },
      "EventUnlockIdentity": {
        "type": "object",
        "required": [
          "id",
          "eventId",
          "name"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable Lensmor identifier for this record."
          },
          "eventId": {
            "type": "string",
            "description": "Public event identifier accepted by event-scoped endpoints."
          },
          "name": {
            "type": [
              "string",
              "null"
            ],
            "description": "Display name when available."
          }
        },
        "description": "Compact identity of the event affected by an unlock operation."
      },
      "EventVisitorUnlockResult": {
        "type": "object",
        "required": [
          "success",
          "alreadyUnlocked",
          "creditsSpent",
          "balanceAfter",
          "event"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether this operation or item completed successfully."
          },
          "alreadyUnlocked": {
            "type": "boolean",
            "description": "Whether the requested access was already available before this call."
          },
          "creditsSpent": {
            "type": "integer",
            "minimum": 0,
            "description": "Credits consumed by this operation."
          },
          "balanceAfter": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/CreditBalance"
              },
              {
                "type": "null"
              }
            ],
            "description": "Credit balance remaining after the operation."
          },
          "event": {
            "$ref": "#/components/schemas/EventUnlockIdentity",
            "description": "Event record associated with this result."
          }
        },
        "description": "Result of requesting the registered Visitor access layer."
      },
      "EventFullAccessUnlockResult": {
        "type": "object",
        "required": [
          "success",
          "alreadyUnlocked",
          "eventUnlocked",
          "visitorUnlocked",
          "visitorSkipped",
          "totalCreditsUsed",
          "balanceAfter",
          "event"
        ],
        "properties": {
          "success": {
            "type": "boolean",
            "description": "Whether this operation or item completed successfully."
          },
          "alreadyUnlocked": {
            "type": "boolean",
            "description": "Whether the requested access was already available before this call."
          },
          "eventUnlocked": {
            "type": "boolean",
            "description": "Whether this call newly unlocked the base event layer."
          },
          "visitorUnlocked": {
            "type": "boolean",
            "description": "Whether this call newly unlocked the registered Visitor layer."
          },
          "visitorSkipped": {
            "type": "boolean",
            "description": "Whether Visitor access was skipped because it was unavailable or not required."
          },
          "totalCreditsUsed": {
            "type": "integer",
            "minimum": 0,
            "description": "Total credits consumed across all requested access layers."
          },
          "balanceAfter": {
            "oneOf": [
              {
                "type": "object",
                "required": [
                  "subscriptionBalance",
                  "permanentBalance",
                  "totalBalance",
                  "unlimited"
                ],
                "properties": {
                  "subscriptionBalance": {
                    "type": "number",
                    "description": "Subscription credits currently available to spend."
                  },
                  "permanentBalance": {
                    "type": "number",
                    "description": "Permanent Balance returned as part of this event full access unlock result object."
                  },
                  "totalBalance": {
                    "type": "number",
                    "description": "Total credits currently available to spend across all buckets."
                  },
                  "unlimited": {
                    "type": "boolean",
                    "description": "Unlimited returned as part of this event full access unlock result object."
                  }
                },
                "additionalProperties": true
              },
              {
                "type": "null"
              }
            ],
            "description": "Credit balance remaining after the operation."
          },
          "event": {
            "$ref": "#/components/schemas/EventUnlockIdentity",
            "description": "Event record associated with this result."
          }
        },
        "description": "Result of atomically requesting all available event access layers."
      },
      "ExhibitorBase": {
        "type": "object",
        "required": [
          "id",
          "companyName",
          "matched_event_ids"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable Lensmor identifier for this record."
          },
          "companyName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company display name when available."
          },
          "domain": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized company domain when available."
          },
          "description": {
            "type": [
              "string",
              "null"
            ],
            "description": "Public description when available."
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company website URL when available."
          },
          "industry": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized company industry when available."
          },
          "employeeCount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Known company employee count when available."
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "description": "Country associated with the record when available."
          },
          "logo": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company logo URL when available."
          },
          "dataSource": {
            "type": [
              "string",
              "null"
            ],
            "description": "Source label for the returned Lensmor record."
          },
          "linkedinUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "LinkedIn company or person profile URL when available."
          },
          "fundingRound": {
            "type": [
              "string",
              "null"
            ],
            "description": "Latest known funding-round label when available."
          },
          "matched_event_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Event identifiers that contributed to the exhibitor match."
          },
          "isRecommended": {
            "type": "boolean",
            "description": "Whether the exhibitor is currently marked as recommended for the caller."
          },
          "recommendationRank": {
            "type": [
              "integer",
              "null"
            ],
            "description": "One-based recommendation rank when scoring is ready."
          },
          "matchStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "Current recommendation or matching processing state."
          },
          "matchScore": {
            "type": [
              "number",
              "null"
            ],
            "description": "Numeric profile-match score when available."
          },
          "matchTier": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized match tier when available."
          },
          "matchReason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Human-readable explanation for the exhibitor match when available."
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Category labels associated with the company or event."
          }
        },
        "additionalProperties": true,
        "description": "Shared public exhibitor company identity, enrichment, and recommendation fields."
      },
      "ExhibitorSignalFields": {
        "type": "object",
        "properties": {
          "techStacks": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Known technology-stack labels associated with the company."
          },
          "buyingSignalTags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Normalized buying-signal labels associated with the exhibitor."
          },
          "buyingSignalStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "Latest buying-signal batch state. On /external/exhibitors/list it is one of ready, processing, pending, or null. On the search endpoints it is always null."
          },
          "buyingSignals": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "signalTag",
                "signalScore",
                "analyzedAt"
              ],
              "properties": {
                "signalTag": {
                  "type": "string",
                  "description": "Signal Tag returned as part of this exhibitor signal fields object."
                },
                "signalDate": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Signal Date returned as part of this exhibitor signal fields object."
                },
                "sourceType": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Buying-signal evidence source category when available."
                },
                "sourceTitle": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Source Title returned as part of this exhibitor signal fields object."
                },
                "sourceUrl": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Source Url returned as part of this exhibitor signal fields object."
                },
                "evidenceSummary": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Evidence Summary returned as part of this exhibitor signal fields object."
                },
                "relevanceToIcp": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Relevance To Icp returned as part of this exhibitor signal fields object."
                },
                "recommendedPlay": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Recommended Play returned as part of this exhibitor signal fields object."
                },
                "signalScore": {
                  "type": "number",
                  "description": "Signal Score returned as part of this exhibitor signal fields object."
                },
                "confidence": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Confidence returned as part of this exhibitor signal fields object."
                },
                "directOrInferred": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Direct Or Inferred returned as part of this exhibitor signal fields object."
                },
                "analyzedAt": {
                  "type": "string",
                  "description": "Analyzed At returned as part of this exhibitor signal fields object."
                }
              }
            },
            "description": "Structured buying-signal evidence when available."
          }
        },
        "description": "Optional technology and buying-signal enrichment for an exhibitor."
      },
      "ExhibitorItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ExhibitorBase"
          },
          {
            "$ref": "#/components/schemas/ExhibitorSignalFields"
          }
        ],
        "description": "Exhibitor list item composed from base company and signal fields."
      },
      "ExhibitorProfile": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ExhibitorBase"
          },
          {
            "type": "object",
            "properties": {
              "events": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string",
                      "description": "Stable Lensmor identifier for this record."
                    },
                    "eventId": {
                      "type": "string",
                      "description": "Public event identifier accepted by event-scoped endpoints."
                    },
                    "name": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "Display name when available."
                    }
                  }
                },
                "description": "Events returned as part of this exhibitor profile object."
              }
            }
          }
        ],
        "description": "Detailed exhibitor profile composed from shared company and signal fields."
      },
      "ExhibitorPage": {
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExhibitorItem"
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "total": {
            "type": "integer",
            "description": "Total matching records across all pages."
          },
          "page": {
            "type": "integer",
            "description": "One-based page number returned."
          },
          "pageSize": {
            "type": "integer",
            "description": "Maximum records requested for this page."
          },
          "totalPages": {
            "type": "integer",
            "description": "Total pages available for the current query."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another result page is available."
          }
        },
        "description": "Standard paginated collection of exhibitors."
      },
      "ExhibitorPageWithSemantics": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ExhibitorPage"
          },
          {
            "type": "object",
            "properties": {
              "recommendationProcessing": {
                "type": "boolean",
                "description": "Whether recommendation computation is still in progress."
              },
              "semantics": {
                "$ref": "#/components/schemas/AccessSemantics",
                "description": "Semantics returned as part of this exhibitor page with semantics object."
              },
              "recommendationProcessingFeature": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Recommendation Processing Feature returned as part of this exhibitor page with semantics object."
              }
            }
          }
        ],
        "description": "Paginated exhibitors plus event-access and preview semantics."
      },
      "ContactItem": {
        "type": "object",
        "description": "Public personnel/contact record with identity, access state, and optional unlocked values.",
        "required": [
          "id",
          "fullName",
          "contactUnlockStatus"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Personnel identifier to pass to profile, event, email-unlock, phone-unlock, and outreach workflows.",
            "example": "101"
          },
          "fullName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Person's display name when available.",
            "example": "Jane Doe"
          },
          "title": {
            "type": [
              "string",
              "null"
            ],
            "description": "Current job title when available.",
            "example": "VP Marketing"
          },
          "department": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized department label when available.",
            "example": "marketing"
          },
          "seniorityLevel": {
            "type": [
              "string",
              "null"
            ],
            "description": "Normalized seniority label when available.",
            "example": "vp"
          },
          "linkedinUrl": {
            "type": [
              "string",
              "null"
            ],
            "description": "LinkedIn profile URL when available.",
            "example": "https://linkedin.com/in/jane"
          },
          "companyName": {
            "type": [
              "string",
              "null"
            ],
            "description": "Company associated with the person when available.",
            "example": "Acme"
          },
          "sourceType": {
            "type": "array",
            "description": "Lensmor source/business labels for this person. Source labels are not mutually exclusive. Product mapping: Exhibitor is exhibitor, Social Signals is social, and Visitor is visitors. Visitor represents registered attendees obtained through organizer or data-provider partnerships; Social Signals is not proof of official registration. Event personnel lists return event-scoped labels, while personnel profile and contact search can aggregate labels across associated events.",
            "items": {
              "type": "string",
              "enum": [
                "exhibitor",
                "social",
                "visitors"
              ]
            }
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "description": "Email address when already accessible to the caller; otherwise `null`. Search endpoints do not unlock it.",
            "example": null
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Phone number when already accessible to the caller; otherwise `null`. Search endpoints do not unlock it.",
            "example": null
          },
          "contactUnlockStatus": {
            "type": "string",
            "description": "Current email/contact access state for the authenticated API key owner.",
            "example": "locked"
          },
          "phoneUnlockStatus": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "ready",
              "processing",
              "failed",
              null
            ],
            "description": "Phone unlock state: `ready`, `processing`, `failed`, or `null` when no phone-unlock state is available.",
            "example": null
          },
          "linkedinActivity": {
            "type": [
              "object",
              "null"
            ],
            "description": "LinkedIn activity summary when populated by the endpoint; otherwise `null`.",
            "properties": {
              "activityLevel": {
                "type": "string",
                "description": "Normalized LinkedIn activity level."
              },
              "isActive": {
                "type": "boolean",
                "description": "Whether recent LinkedIn activity indicates that the person is active."
              },
              "latestPostAt": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Timestamp of the latest known LinkedIn post when available."
              }
            }
          },
          "linkedinActivityStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "LinkedIn activity analysis state when populated by the endpoint; otherwise `null`.",
            "example": null
          },
          "eventCount": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Number of Lensmor events associated with the person when available.",
            "example": 3
          },
          "outreachMessageStatus": {
            "type": [
              "string",
              "null"
            ],
            "description": "Current outreach generation state when this endpoint includes outreach metadata."
          },
          "outreachMessageChannels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Generated or requested outreach channels when outreach metadata is present."
          }
        }
      },
      "ContactPage": {
        "type": "object",
        "description": "Standard paginated collection of contact records.",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "description": "Contact records returned on the current page.",
            "items": {
              "$ref": "#/components/schemas/ContactItem"
            }
          },
          "total": {
            "type": "integer",
            "description": "Total matching contacts across all pages.",
            "example": 1
          },
          "page": {
            "type": "integer",
            "description": "One-based page number returned.",
            "example": 1
          },
          "pageSize": {
            "type": "integer",
            "description": "Requested maximum number of contacts per page.",
            "example": 20
          },
          "totalPages": {
            "type": "integer",
            "description": "Total number of pages for the current search.",
            "example": 1
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another page is available after the current page.",
            "example": false
          }
        }
      },
      "ContactPageWithSemantics": {
        "allOf": [
          {
            "$ref": "#/components/schemas/ContactPage"
          },
          {
            "type": "object",
            "properties": {
              "semantics": {
                "$ref": "#/components/schemas/AccessSemantics",
                "description": "Semantics returned as part of this contact page with semantics object."
              }
            }
          }
        ],
        "description": "Paginated contacts plus event-access and preview semantics."
      },
      "AccessSemantics": {
        "type": "object",
        "properties": {
          "accessMode": {
            "type": "string",
            "enum": [
              "preview",
              "full"
            ],
            "description": "Base-event access mode for this result: `preview` or `full`."
          },
          "previewLimit": {
            "type": [
              "integer",
              "null"
            ],
            "description": "Maximum preview records when preview mode applies, otherwise `null`."
          },
          "counts": {
            "type": "object",
            "properties": {
              "actualTotal": {
                "type": "integer",
                "description": "Actual Total returned as part of this access semantics object."
              },
              "visibleTotal": {
                "type": "integer",
                "description": "Visible Total returned as part of this access semantics object."
              },
              "remainingLockedCount": {
                "type": "integer",
                "description": "Remaining Locked Count returned as part of this access semantics object."
              }
            },
            "additionalProperties": true,
            "description": "Visible and available record counts used to explain coverage."
          },
          "pageState": {
            "type": "object",
            "properties": {
              "requestedPage": {
                "type": "integer",
                "description": "Requested Page returned as part of this access semantics object."
              },
              "accessible": {
                "type": "boolean",
                "description": "Accessible returned as part of this access semantics object."
              },
              "maxAccessiblePage": {
                "type": "integer",
                "description": "Max Accessible Page returned as part of this access semantics object."
              }
            },
            "additionalProperties": true,
            "description": "Pagination state after applying access and preview rules."
          },
          "unlock": {
            "type": "object",
            "properties": {
              "requiredForMoreResults": {
                "type": "boolean",
                "description": "Required For More Results returned as part of this access semantics object."
              },
              "actionType": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Action Type returned as part of this access semantics object."
              },
              "credits": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Credits expected for the action under the current state."
              }
            },
            "additionalProperties": true,
            "description": "Unlock eligibility, cost, and state metadata for the current scope."
          },
          "guidance": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "description": "Numeric or symbolic code that identifies the response or business condition."
              },
              "message": {
                "type": "string",
                "description": "Human-readable explanation suitable for logs or user-facing error handling."
              }
            },
            "additionalProperties": true,
            "description": "Structured integration guidance for the current access state."
          }
        },
        "additionalProperties": true,
        "description": "Metadata explaining preview/full access, visible counts, page state, and unlock guidance."
      },
      "ContactUnlockSubmission": {
        "type": "object",
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "success"
            ],
            "description": "accepted when an asynchronous task was created; success when there was no chargeable work to enqueue."
          },
          "task_id": {
            "type": "string",
            "description": "TaskCenter identifier. Present when status is accepted.",
            "pattern": "^[0-9]+$",
            "example": "321"
          },
          "job_id": {
            "type": "string",
            "description": "Alias of task_id. Present when status is accepted.",
            "pattern": "^[0-9]+$",
            "example": "321"
          },
          "skipped_personnel_ids": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Submitted personnel identifiers that did not create chargeable work."
          },
          "skipped_detail": {
            "type": "object",
            "properties": {
              "invalid_personnel_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Invalid personnel ids returned as part of this contact unlock submission object."
              },
              "missing_personnel_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Missing personnel ids returned as part of this contact unlock submission object."
              },
              "unlinked_personnel_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Unlinked personnel ids returned as part of this contact unlock submission object."
              },
              "already_unlocked_personnel_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Already unlocked personnel ids returned as part of this contact unlock submission object."
              },
              "unlocking_personnel_ids": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Unlocking personnel ids returned as part of this contact unlock submission object."
              }
            },
            "description": "Reasons submitted personnel records were skipped, grouped by condition."
          }
        },
        "oneOf": [
          {
            "properties": {
              "status": {
                "const": "accepted",
                "description": "Current normalized status for the submission, task, or generated content."
              }
            },
            "required": [
              "task_id",
              "job_id"
            ]
          },
          {
            "properties": {
              "status": {
                "const": "success",
                "description": "Current normalized status for the submission, task, or generated content."
              }
            }
          }
        ],
        "description": "Email or phone unlock submission outcome, including accepted work and skipped records."
      },
      "ContactUnlockTask": {
        "type": "object",
        "required": [
          "taskId",
          "taskStatus",
          "items"
        ],
        "properties": {
          "taskId": {
            "type": "string",
            "description": "Asynchronous task identifier.",
            "pattern": "^[0-9]+$",
            "example": "321"
          },
          "taskStatus": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ],
            "description": "Current task lifecycle state."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "personnelId",
                "status"
              ],
              "properties": {
                "personnelId": {
                  "type": "string",
                  "description": "Personnel Id returned as part of this contact unlock task object."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "processing",
                    "unlocked",
                    "failed"
                  ],
                  "description": "Current normalized status for the submission, task, or generated content."
                },
                "email": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Email address when already accessible; otherwise `null`."
                },
                "errorCode": {
                  "type": "string",
                  "description": "Error Code returned as part of this contact unlock task object."
                }
              }
            },
            "description": "Records returned on the current page or in the current batch."
          }
        },
        "description": "Asynchronous email unlock task and its item-level results."
      },
      "ProfileEventRecommendationPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventPage"
          },
          {
            "type": "object",
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "completed",
                  "completed_empty"
                ],
                "description": "Synchronous recommendation outcome: results returned or no matching events found."
              },
              "condition_tags": {
                "type": "object",
                "additionalProperties": true,
                "description": "Condition tags returned as part of this profile event recommendation page object."
              },
              "profile_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Profile version returned as part of this profile event recommendation page object."
              },
              "active_result_version": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Active result version returned as part of this profile event recommendation page object."
              },
              "is_stale": {
                "type": "boolean",
                "description": "Is stale returned as part of this profile event recommendation page object."
              },
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/ProfileRecommendedEvent"
                },
                "description": "Recommended event records for the requested page."
              }
            },
            "additionalProperties": true,
            "required": [
              "status",
              "condition_tags",
              "profile_version",
              "active_result_version",
              "is_stale"
            ]
          }
        ],
        "description": "Paginated profile-matched events and recommendation metadata."
      },
      "ActionPrecheckRequest": {
        "type": "object",
        "required": [
          "action_type",
          "params"
        ],
        "properties": {
          "action_type": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "examples": [
              "query_event_personnel",
              "unlock_event_contacts",
              "unlock_event_visitors",
              "unlock_event_full_access",
              "unlock_contact_emails",
              "unlock_contact_phones",
              "search_exhibitor_events",
              "search_personnel_events_by_name",
              "integration_status",
              "integration_export_contacts",
              "integration_export_exhibitors",
              "others"
            ],
            "description": "Action to evaluate. The listed examples are handled explicitly. Other 1–100 character strings are accepted and return `allowed: false` with `reason_code: unsupported_action`.",
            "example": "unlock_contact_emails"
          },
          "call_source": {
            "type": "string",
            "description": "Caller source label, typically `api` or `agent`.",
            "example": "api",
            "minLength": 1,
            "maxLength": 100
          },
          "params": {
            "type": "object",
            "additionalProperties": true,
            "description": "Action-specific identifiers and inputs, such as an `event_id`.",
            "example": {
              "event_id": "26855"
            }
          },
          "locale": {
            "type": "string",
            "description": "Optional locale used for localized guidance or messages.",
            "example": "en-US",
            "minLength": 1,
            "maxLength": 20
          },
          "trace_id": {
            "type": "string",
            "description": "Optional caller-provided trace identifier for support correlation.",
            "example": "trace_123",
            "minLength": 1,
            "maxLength": 200
          },
          "conversation_id": {
            "type": "string",
            "description": "Optional conversation identifier for agent workflows.",
            "example": "conversation_123",
            "minLength": 1,
            "maxLength": 200
          },
          "channel_message_id": {
            "type": "string",
            "description": "Optional channel message identifier for agent workflows.",
            "example": "message_123",
            "minLength": 1,
            "maxLength": 200
          }
        },
        "additionalProperties": false,
        "description": "Read-only action eligibility and expected-credit evaluation request."
      },
      "ActionPrecheckResponse": {
        "type": "object",
        "required": [
          "ok",
          "action_type",
          "allowed",
          "should_charge",
          "credits",
          "reason_code",
          "biz_code",
          "detail"
        ],
        "properties": {
          "ok": {
            "type": "boolean",
            "const": true,
            "description": "Whether the precheck itself completed successfully."
          },
          "action_type": {
            "type": "string",
            "description": "Action evaluated by the precheck."
          },
          "allowed": {
            "type": "boolean",
            "description": "Whether the action is currently allowed to proceed."
          },
          "should_charge": {
            "type": "boolean",
            "description": "Whether executing the action is expected to consume credits."
          },
          "credits": {
            "type": "integer",
            "description": "Credits expected for the action under the current state."
          },
          "reason_code": {
            "type": "string",
            "enum": [
              "ok",
              "already_unlocked",
              "unlock_in_progress",
              "state_conflict",
              "insufficient_balance",
              "no_contacts_available",
              "exceed_max_unlock_limit",
              "invalid_subject",
              "unsupported_action",
              "not_found",
              "forbidden",
              "system_error"
            ],
            "description": "Stable reason explaining the eligibility and charging decision."
          },
          "biz_code": {
            "type": "string",
            "description": "Business code associated with the precheck decision."
          },
          "detail": {
            "type": "object",
            "additionalProperties": true,
            "description": "Action-specific eligibility, cost, or state detail."
          }
        },
        "additionalProperties": true,
        "description": "Action eligibility, expected charging, reason, and action-specific detail."
      },
      "LinkedinActivityUnlockRequest": {
        "type": "object",
        "required": [
          "personnel_ids"
        ],
        "properties": {
          "personnel_ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2000,
            "items": {
              "type": "string"
            },
            "description": "Lensmor personnel identifiers selected for this batch operation.",
            "example": [
              "789"
            ]
          },
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 20,
            "description": "Optional Lensmor event identifier returned as `id` or `eventId`. When omitted, event membership validation is skipped.",
            "example": "26855"
          }
        },
        "additionalProperties": false,
        "description": "Batch LinkedIn activity analysis request with optional event context."
      },
      "LinkedinActivityUnlockItem": {
        "type": "object",
        "required": [
          "personnel_id",
          "success",
          "alreadyUnlocked",
          "taskId",
          "error"
        ],
        "properties": {
          "personnel_id": {
            "type": "string",
            "description": "Lensmor personnel identifier for this item."
          },
          "success": {
            "type": "boolean",
            "description": "Whether this operation or item completed successfully."
          },
          "alreadyUnlocked": {
            "type": "boolean",
            "description": "Whether the requested access was already available before this call."
          },
          "taskId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Numeric child-task identifier for existing in-progress work; newly accepted items can return `null` while child dispatch is queued.",
            "pattern": "^[0-9]+$"
          },
          "error": {
            "type": [
              "string",
              "null"
            ],
            "description": "Item-level error message when the operation failed, otherwise `null`."
          }
        },
        "description": "Item-level LinkedIn activity submission outcome for one person."
      },
      "LinkedinActivityUnlockResponse": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/LinkedinActivityUnlockItem"
            },
            "description": "Records returned on the current page or in the current batch."
          }
        },
        "description": "Batch LinkedIn activity submission outcomes."
      },
      "PhoneUnlockRequest": {
        "type": "object",
        "required": [
          "personnel_ids"
        ],
        "properties": {
          "personnel_ids": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2000,
            "items": {
              "type": "string"
            },
            "description": "Lensmor personnel identifiers selected for this batch operation.",
            "example": [
              "789"
            ]
          },
          "event_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Optional Lensmor event identifier returned as `id` or `eventId`. When omitted, event membership validation is skipped.",
            "example": "26855"
          }
        },
        "description": "Batch phone enrichment request with optional event context."
      },
      "PhoneUnlockTask": {
        "type": "object",
        "required": [
          "taskId",
          "taskStatus",
          "items"
        ],
        "properties": {
          "taskId": {
            "type": "string",
            "description": "Asynchronous task identifier.",
            "pattern": "^[0-9]+$",
            "example": "321"
          },
          "taskStatus": {
            "type": "string",
            "enum": [
              "pending",
              "processing",
              "completed",
              "failed"
            ],
            "description": "Current task lifecycle state."
          },
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "personnelId",
                "status"
              ],
              "properties": {
                "personnelId": {
                  "type": "string",
                  "description": "Personnel Id returned as part of this phone unlock task object."
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "pending",
                    "processing",
                    "unlocked",
                    "failed"
                  ],
                  "description": "Current normalized status for the submission, task, or generated content."
                },
                "phone": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Phone number when already accessible; otherwise `null`."
                },
                "errorCode": {
                  "type": "string",
                  "description": "Error Code returned as part of this phone unlock task object."
                }
              }
            },
            "description": "Records returned on the current page or in the current batch."
          }
        },
        "description": "Asynchronous phone unlock task and its item-level results."
      },
      "OutreachMessageRequest": {
        "type": "object",
        "required": [
          "personnel_ids",
          "channels"
        ],
        "properties": {
          "personnel_ids": {
            "type": "array",
            "maxItems": 2000,
            "items": {
              "type": "string"
            },
            "description": "Lensmor personnel identifiers selected for this batch operation. The runtime accepts an empty array, but useful generation requires at least one identifier.",
            "example": [
              "789"
            ]
          },
          "event_id": {
            "type": "string",
            "description": "Optional internal Lensmor event row identifier from the event response `id` field. This endpoint currently converts the value directly to `BigInt`; unlike most event-scoped routes, it does not resolve public `eventId`. Omit it to skip membership validation and event context.",
            "example": "501",
            "pattern": "^[0-9]+$"
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "email",
                "linkedin_message"
              ]
            },
            "description": "Output channels to generate: `email`, `linkedin_message`, or both. The runtime accepts an empty array, but an empty array creates no useful output.",
            "example": [
              "email",
              "linkedin_message"
            ]
          },
          "linkedin_message_types": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "inmail",
                "connection_note",
                "connected_message"
              ]
            },
            "description": "LinkedIn variants to generate: `inmail`, `connection_note`, and/or `connected_message`.",
            "example": [
              "inmail",
              "connection_note"
            ]
          },
          "outreach_purpose": {
            "type": "string",
            "description": "Optional offer, call-to-action, or purpose context used to personalize the drafts.",
            "example": "Invite the contact to a product demo"
          }
        },
        "description": "Batch AI outreach generation request for selected channels and personnel."
      },
      "OutreachMessageResponse": {
        "type": "object",
        "required": [
          "items"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "personnel_id",
                "success",
                "taskId",
                "error"
              ],
              "properties": {
                "personnel_id": {
                  "type": "string",
                  "description": "Lensmor personnel identifier for this item."
                },
                "success": {
                  "type": "boolean",
                  "description": "Whether this operation or item completed successfully."
                },
                "taskId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Numeric child-task identifier for existing in-progress work; newly accepted items normally return `null` while child dispatch is queued.",
                  "pattern": "^[0-9]+$"
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "Item-level error message when the operation failed, otherwise `null`."
                }
              }
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "taskCenterId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Numeric TaskCenter identifier returned when at least one outreach generation task was created.",
            "pattern": "^[0-9]+$",
            "example": "321"
          }
        },
        "description": "Item-level outreach generation submissions and optional batch task identity."
      },
      "OutreachDetail": {
        "type": "object",
        "required": [
          "found",
          "channels",
          "messages"
        ],
        "properties": {
          "found": {
            "type": "boolean",
            "description": "Whether generated outreach content exists for this personnel-event combination."
          },
          "channels": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Requested or available outreach content channels."
          },
          "messages": {
            "type": "object",
            "properties": {
              "email": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Email address when already accessible; otherwise `null`."
              },
              "linkedin_message": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Linkedin message returned as part of this outreach detail object."
              },
              "linkedin": {
                "type": "object",
                "properties": {
                  "inmail": {
                    "type": "object",
                    "properties": {
                      "subject": {
                        "type": "string",
                        "description": "Generated email or InMail subject when applicable."
                      },
                      "body": {
                        "type": "string",
                        "description": "Generated message body."
                      }
                    },
                    "description": "Inmail returned as part of this outreach detail object."
                  },
                  "connection_note": {
                    "type": "object",
                    "properties": {
                      "body": {
                        "type": "string",
                        "description": "Generated message body."
                      }
                    },
                    "description": "Connection note returned as part of this outreach detail object."
                  },
                  "connected_message": {
                    "type": "object",
                    "properties": {
                      "body": {
                        "type": "string",
                        "description": "Generated message body."
                      }
                    },
                    "description": "Connected message returned as part of this outreach detail object."
                  }
                },
                "description": "Linkedin returned as part of this outreach detail object."
              }
            },
            "description": "Generated outreach content organized by channel and message variant."
          },
          "reason": {
            "type": [
              "string",
              "null"
            ],
            "description": "Human-readable reason or absence explanation when available."
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Evidence or source references used during generation when available."
          },
          "outreach_purpose": {
            "type": [
              "string",
              "null"
            ],
            "description": "Purpose or offer context used to personalize the outreach."
          },
          "tone": {
            "type": [
              "string",
              "null"
            ],
            "description": "Tone selected or inferred for the generated content."
          },
          "status": {
            "type": [
              "string",
              "null"
            ],
            "description": "Current outreach message status, such as processing, ready, or failed. Null when no record exists."
          },
          "create_time": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Record creation timestamp in milliseconds. Null when no record exists."
          },
          "update_time": {
            "type": [
              "integer",
              "null"
            ],
            "format": "int64",
            "description": "Record update timestamp in milliseconds. Null when no record exists."
          }
        },
        "description": "Latest generated outreach content and metadata for one personnel-event combination."
      },
      "FeatureUnavailableBusinessError": {
        "type": "object",
        "required": [
          "code",
          "message",
          "errorKey",
          "traceId"
        ],
        "properties": {
          "code": {
            "type": "integer",
            "const": 400,
            "description": "Business code returned in an HTTP 200 response for this paid-feature guard."
          },
          "message": {
            "type": "string",
            "description": "Human-readable explanation suitable for logs or user-facing error handling."
          },
          "errorKey": {
            "type": "string",
            "const": "USER_HAS_NO_FEATURE",
            "description": "Stable machine-readable error key for a feature unavailable to free users."
          },
          "traceId": {
            "type": "string",
            "description": "Request trace identifier to include in support or incident reports."
          },
          "details": {
            "description": "Optional structured error details; normally omitted for this business guard."
          }
        },
        "additionalProperties": false,
        "description": "HTTP 200 business-error envelope returned when an active paid subscription is required."
      },
      "ProfileRecommendedEvent": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventDetail"
          },
          {
            "type": "object",
            "required": [
              "matched_exhibitor_count",
              "matched_personnel_count",
              "match_score",
              "unlocked",
              "rank"
            ],
            "properties": {
              "declaredExpectedAttendees": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Organizer-declared expected attendee count when available."
              },
              "estimatedExpectedAttendees": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Estimated expected attendee count serialized as a string when available."
              },
              "quality": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Event quality label when available."
              },
              "sourceTags": {
                "type": "array",
                "items": {
                  "type": "string"
                },
                "description": "Source classification tags associated with the event."
              },
              "visibilityStatus": {
                "type": "integer",
                "description": "Event visibility state returned by the service."
              },
              "previewPersonnelCount": {
                "type": [
                  "integer",
                  "null"
                ],
                "description": "Preview personnel count when populated for the event."
              },
              "createTime": {
                "type": "string",
                "pattern": "^[0-9]+$",
                "description": "Creation time as a millisecond timestamp serialized to a decimal string."
              },
              "updateTime": {
                "type": "string",
                "pattern": "^[0-9]+$",
                "description": "Last update time as a millisecond timestamp serialized to a decimal string."
              },
              "matched_exhibitor_count": {
                "type": "integer",
                "description": "Number of exhibitors matched to the supplied profile for this event."
              },
              "matched_personnel_count": {
                "type": "integer",
                "description": "Number of personnel matched to the supplied profile for this event."
              },
              "match_score": {
                "type": [
                  "number",
                  "null"
                ],
                "minimum": 0,
                "maximum": 1,
                "description": "Profile-to-event match score, or `null` when the scorer did not return one."
              },
              "unlocked": {
                "type": "boolean",
                "description": "Whether base event access is already unlocked for the API key owner."
              },
              "relevanceReason": {
                "type": [
                  "string",
                  "null"
                ],
                "description": "Human-readable recommendation reason when generated; otherwise omitted or `null`."
              },
              "rank": {
                "type": "integer",
                "minimum": 1,
                "description": "One-based recommendation rank returned by the ICP recommendation pipeline."
              }
            }
          }
        ],
        "description": "Full Lensmor event metadata plus profile-recommendation evidence and rank."
      },
      "ExhibitorRelatedEventItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventItem"
          },
          {
            "type": "object",
            "required": [
              "attendance_identity"
            ],
            "properties": {
              "attendance_identity": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "exhibitor",
                    "visitor"
                  ]
                },
                "description": "Complete attendance identities for this company at this event. An event matched by a scope still returns its complete identity array.",
                "example": [
                  "exhibitor",
                  "visitor"
                ]
              }
            }
          }
        ],
        "description": "Event returned by a company reverse lookup with event-scoped attendance identities."
      },
      "PersonnelRelatedEventItem": {
        "allOf": [
          {
            "$ref": "#/components/schemas/EventItem"
          },
          {
            "type": "object",
            "required": [
              "attendance_identity"
            ],
            "properties": {
              "attendance_identity": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "exhibitor_employee",
                    "visitor"
                  ]
                },
                "description": "Complete attendance identities for the matched personnel at this event. Exact-name lookups combine evidence across matched personnel records before filtering. Scope filtering does not trim the returned identity array.",
                "example": [
                  "exhibitor_employee",
                  "visitor"
                ]
              }
            }
          }
        ],
        "description": "Event returned by a person reverse lookup with event-scoped attendance identities."
      },
      "ExhibitorRelatedEventPage": {
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ExhibitorRelatedEventItem"
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "total": {
            "type": "integer",
            "description": "Total matching records across all pages."
          },
          "page": {
            "type": "integer",
            "description": "One-based page number returned."
          },
          "pageSize": {
            "type": "integer",
            "description": "Maximum records requested for this page."
          },
          "totalPages": {
            "type": "integer",
            "description": "Total pages available for the current query."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another result page is available."
          }
        },
        "additionalProperties": true,
        "description": "Paginated company-related events with attendance identities."
      },
      "PersonnelRelatedEventPage": {
        "type": "object",
        "required": [
          "items",
          "total",
          "page",
          "pageSize",
          "totalPages",
          "hasMore"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PersonnelRelatedEventItem"
            },
            "description": "Records returned on the current page or in the current batch."
          },
          "total": {
            "type": "integer",
            "description": "Total matching records across all pages."
          },
          "page": {
            "type": "integer",
            "description": "One-based page number returned."
          },
          "pageSize": {
            "type": "integer",
            "description": "Maximum records requested for this page."
          },
          "totalPages": {
            "type": "integer",
            "description": "Total pages available for the current query."
          },
          "hasMore": {
            "type": "boolean",
            "description": "Whether another result page is available."
          }
        },
        "additionalProperties": true,
        "description": "Paginated person-related events with attendance identities."
      }
    }
  }
}
