Skip to main content

External API Endpoint Inventory

Rules

  • Source of truth for method/path: controllers
  • Source of truth for request contracts: controller + DTO
  • Source of truth for response contracts: service + mapper + runtime output shape
  • Source of truth for auth/error behavior: runtime middleware and external error path
  • Tests are not used as contract evidence in this document

Shared runtime truths

  • Authorization header format: Authorization: Bearer uak_...
  • Bearer scheme stripping is case-insensitive at runtime
  • All current external controller routes require authentication through the external API auth flow
  • External error responses use the public envelope { code, message, errorKey, traceId }
  • Paginated success responses use { items, total, page, pageSize, totalPages, hasMore }, with totalPages: 0 when total is 0

Endpoint table

MethodPathController fileAuth requiredSuccess statusPublished in MintlifyNotes
GET/external/events/listsrc/modules/external-api/controllers/external-events.controller.tsYes200 OKYesDefault date window is yesterday through one year ahead when no date filter is provided
POST/external/events/fit-scoresrc/modules/external-api/controllers/external-events.controller.tsYes201 CreatedYesevent_id accepts either Event.eventId or internal Event.id
POST/external/events/ranksrc/modules/external-api/controllers/external-events.controller.tsYes201 CreatedYesevent_ids accepts either Event.eventId or internal Event.id
GET/external/events/briefsrc/modules/external-api/controllers/external-events.controller.tsYes200 OKYesevent_id accepts either Event.eventId or internal Event.id
GET/external/events/:idsrc/modules/external-api/controllers/external-events.controller.tsYes200 OKYesPath :id accepts either internal row id or external eventId
GET/external/exhibitors/listsrc/modules/external-api/controllers/external-exhibitors.controller.tsYes200 OKYesevent_id accepts either Event.eventId or internal Event.id
POST/external/exhibitors/searchsrc/modules/external-api/controllers/external-exhibitors.controller.tsYes201 CreatedYesRequires company_url, target_audience, or both; no-match cases stay 200/201 success with empty items
POST/external/exhibitors/search-by-company-namesrc/modules/external-api/controllers/external-exhibitors.controller.tsYes201 CreatedYesPrecision-first paged lookup by company_name
POST/external/exhibitors/search-eventssrc/modules/external-api/controllers/external-exhibitors.controller.tsYes201 CreatedYesReverse lookup from company_name to matching events
GET/external/exhibitors/profilesrc/modules/external-api/controllers/external-exhibitors.controller.tsYes200 OKYesexhibitor_id is a numeric string
GET/external/exhibitors/eventssrc/modules/external-api/controllers/external-exhibitors.controller.tsYes200 OKYesexhibitor_id is a numeric string
GET/external/personnel/listsrc/modules/external-api/controllers/external-personnel.controller.tsYes200 OKYesevent_id accepts either Event.eventId or internal Event.id
GET/external/personnel/profilesrc/modules/external-api/controllers/external-personnel.controller.tsYes200 OKYespersonnel_id is a numeric string
GET/external/personnel/events/by-linkedinsrc/modules/external-api/controllers/external-personnel.controller.tsYes200 OKYeslinkedin_url normalizes to a LinkedIn profile URL, then returns the matched personnel profile plus paginated associated events
GET/external/personnel/eventssrc/modules/external-api/controllers/external-personnel.controller.tsYes200 OKYespersonnel_id is a numeric string
GET/external/contacts/searchsrc/modules/external-api/controllers/external-contacts.controller.tsYes200 OKYesSearch is scoped to the authenticated user context
POST/external/profile-matching/recommendations/events/pagedsrc/modules/external-api/controllers/external-profile-matching.controller.tsYes201 CreatedYesRuns synchronous apply-onboarding, then returns paged recommended events
GET/external/profile-matching/recommendations/exhibitorssrc/modules/external-api/controllers/external-profile-matching.controller.tsYes200 OKYesevent_id accepts either Event.eventId or internal Event.id

GET /external/events/list

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.
keywordNostringFree-text event search.
countryNostringCountry filter.
cityNostringCity filter.
date_start_fromNoYYYY-MM-DD stringOptional lower date bound.
date_start_toNoYYYY-MM-DD stringOptional upper date bound.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Event summaries for the current page.
totalintegerTotal matched rows.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

items[] fields

FieldTypeNotes
idstringInternal event row identifier.
eventIdstringExternal event identifier.
namestringEvent name.
nicknamestring or nullEvent short name.
descriptionstring or nullEvent description.
urlstring or nullEvent website URL.
dateStartYYYY-MM-DD string or nullStart date.
dateEndYYYY-MM-DD string or nullEnd date.
venuestring or nullVenue name.
citystring or nullCity.
regionstring or nullRegion or state.
countrystring or nullCountry.
exhibitorCountinteger or nullExhibitor count snapshot.
imagestring or nullImage URL.
dataSourcestring or nullUpstream data source label.

Response example

{
  "items": [
    {
      "id": "123",
      "eventId": "139574",
      "name": "Shoptalk",
      "nickname": null,
      "description": null,
      "url": "https://example.com",
      "dateStart": "2026-03-25",
      "dateEnd": "2026-03-28",
      "venue": "Convention Center",
      "city": "Las Vegas",
      "region": "Nevada",
      "country": "United States",
      "exhibitorCount": 250,
      "image": null,
      "dataSource": "vendelux"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 401 Unauthorized when the API key is missing, malformed, or invalid.

Notes

  • When neither date_start_from nor date_start_to is supplied, the runtime defaults to events starting from yesterday through one year from now.
  • List-summary items intentionally omit attendeeCount and personnelCount; those values were removed from this response because they were inaccurate in list context.

POST /external/events/fit-score

Authentication

Bearer token required.

Success status code

201 Created

Request body

FieldRequiredTypeNotes
event_idYesstringSupports either external Event.eventId or internal Event.id.

Response body

Top-level fields

FieldTypeNotes
eventobjectSame event summary shape as GET /external/events/list items[].
scorenumberNormalized to a 0.0-10.0 style scale.
recommendationstringOne of recommended, consider, or not_recommended.
breakdownobjectContains profile_match, matched_exhibitor_density, and event_scale.

Response example

{
  "event": {
    "id": "123",
    "eventId": "139574",
    "name": "Shoptalk",
    "nickname": null,
    "description": null,
    "url": "https://example.com",
    "dateStart": "2026-03-25",
    "dateEnd": "2026-03-28",
    "venue": "Convention Center",
    "city": "Las Vegas",
    "region": "Nevada",
    "country": "United States",
    "exhibitorCount": 250,
    "image": null,
    "dataSource": "vendelux"
  },
  "score": 7.8,
  "recommendation": "recommended",
  "breakdown": {
    "profile_match": 7.8,
    "matched_exhibitor_density": 2.4,
    "event_scale": 2.5
  }
}

Error responses

  • 400 Bad Request when event_id is missing or invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the target event cannot be resolved.
  • 409 Conflict when the recommendation dependency is still processing.

Notes

  • event_id accepts either the internal row id or external eventId.

POST /external/events/rank

Authentication

Bearer token required.

Success status code

201 Created

Request body

FieldRequiredTypeNotes
event_idsYesstring[]Each value supports either external Event.eventId or internal Event.id.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Ranked event summaries in descending match-score order.

items[] fields

FieldTypeNotes
event_idstringExternal event identifier.
namestringEvent name.
rankintegerOne-based rank in the returned order.
match_scorenumberRaw profile score rounded to two decimals.
reasonsarrayCurrently returned as an empty array.

Response example

{
  "items": [
    {
      "event_id": "139574",
      "name": "Shoptalk",
      "rank": 1,
      "match_score": 0.82,
      "reasons": []
    }
  ]
}

Error responses

  • 400 Bad Request when any event_ids entry is invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when any requested event cannot be resolved.
  • 409 Conflict when the recommendation dependency is still processing.

Notes

  • POST /external/events/rank currently returns an empty reasons array for each item.

GET /external/events/brief

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
event_idYesstringSupports either external Event.eventId or internal Event.id.

Response body

Top-level fields

FieldTypeNotes
eventobjectSame event summary shape as GET /external/events/list items[].
summaryobjectBrief rollup metadata.

summary fields

FieldTypeNotes
attendeeCountintegerDefaults to 0 when absent in storage or when the event has no personnel relations.
exhibitorCountintegerDefaults to 0 when absent in storage.
personnelCountintegerDefaults to 0 when absent in storage or when the event has no personnel relations.
topCategoriesarrayCurrently returned as an empty array.
dataFreshnessstringCurrently hard-coded to database_snapshot.

Response example

{
  "event": {
    "id": "123",
    "eventId": "139574",
    "name": "Shoptalk",
    "nickname": null,
    "description": null,
    "url": "https://example.com",
    "dateStart": "2026-03-25",
    "dateEnd": "2026-03-28",
    "venue": "Convention Center",
    "city": "Las Vegas",
    "region": "Nevada",
    "country": "United States",
    "exhibitorCount": 250,
    "image": null,
    "dataSource": "vendelux"
  },
  "summary": {
    "attendeeCount": 10000,
    "exhibitorCount": 250,
    "personnelCount": 1800,
    "topCategories": [],
    "dataFreshness": "database_snapshot"
  }
}

Error responses

  • 400 Bad Request when event_id is invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the target event cannot be resolved.

Notes

  • GET /external/events/brief currently returns topCategories as an empty array.

GET /external/events/:id

Authentication

Bearer token required.

Success status code

200 OK

Path parameters

NameRequiredTypeNotes
idYesstringAccepts either internal event row id or external eventId.

Response body

Top-level fields

FieldTypeNotes
eventobjectDetailed event payload.

event fields

FieldTypeNotes
idstringInternal event row identifier.
eventIdstringExternal event identifier.
namestring or nullEvent name.
nicknamestring or nullEvent short name.
descriptionstring or nullEvent description.
urlstring or nullEvent website URL.
dateStartYYYY-MM-DD string or nullStart date.
dateEndYYYY-MM-DD string or nullEnd date.
venuestring or nullVenue name.
citystring or nullCity.
regionstring or nullRegion or state.
countrystring or nullCountry.
latitudestring or nullLatitude rendered as a string.
longitudestring or nullLongitude rendered as a string.
attendeeCountinteger or nullnull when the event has no personnel relations; otherwise defaults to 0 when absent.
declaredExpectedAttendeesstring or nullDeclared attendance expectation rendered as a string.
estimatedExpectedAttendeesstring or nullEstimated attendance expectation rendered as a string.
priceLowerstring or nullLower ticket price rendered as a string.
priceUpperstring or nullUpper ticket price rendered as a string.
eventTypestring or nullPrimary event-type label.
categoriesobject[]Event category metadata.
topicsstring[]Topics array parsed from stored JSON or string data.
topicsCountintegerTopic count.
verifiedintegerVerification flag.
futureintegerFuture-event flag.
historicintegerHistoric-event flag.
historicEventstring or nullHistoric event marker.
imagestring or nullImage URL.
dataSourcestring or nullUpstream data source label.
exhibitorCountintegerDefaults to 0 when absent.
personnelCountinteger or nullnull when the event has no personnel relations; otherwise defaults to 0 when absent.
eventTypesobject[]Detailed event-type rows.

event.categories[] fields

FieldTypeNotes
idintegerCategory identifier.
codestringCategory code.
namestringCategory name.
descriptionstring or nullCategory description.
confidencestring or nullConfidence rendered as a string.

event.eventTypes[] fields

FieldTypeNotes
idintegerEvent type identifier.
typeNamestringEvent type name.
slugstringEvent type slug.
isPrimarybooleanPrimary-type marker.

Response example

{
  "event": {
    "id": "123",
    "eventId": "139574",
    "name": "Shoptalk",
    "nickname": null,
    "description": null,
    "url": "https://example.com",
    "dateStart": "2026-03-25",
    "dateEnd": "2026-03-28",
    "venue": "Convention Center",
    "city": "Las Vegas",
    "region": "Nevada",
    "country": "United States",
    "latitude": "36.1147",
    "longitude": "-115.1728",
    "attendeeCount": 10000,
    "declaredExpectedAttendees": null,
    "estimatedExpectedAttendees": null,
    "priceLower": null,
    "priceUpper": null,
    "eventType": null,
    "categories": [],
    "topics": [],
    "topicsCount": 0,
    "verified": 1,
    "future": 1,
    "historic": 0,
    "historicEvent": null,
    "image": null,
    "dataSource": "vendelux",
    "exhibitorCount": 250,
    "personnelCount": 1800,
    "eventTypes": []
  }
}

Error responses

  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the target event cannot be resolved.

Notes

  • GET /external/events/:id accepts either the internal row id or external eventId in the :id segment.
  • Numeric :id values are resolved against internal Event.id first, then retried as external eventId.
  • attendeeCount and personnelCount may be null on detail responses when the event has no personnel relations.

GET /external/exhibitors/list

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
event_idYesstringSupports either external Event.eventId or internal Event.id.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.
keywordNostringExhibitor search term for the event.
countryNostringExhibitor country filter.
categoryNostring[]Exhibitor category filters; repeated query params are supported.
industryNostring[]Exhibitor industry filters; repeated query params are supported.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Exhibitors associated with the resolved event.
totalintegerTotal matched exhibitors.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

items[] fields

FieldTypeNotes
idstringInternal exhibitor row identifier.
companyNamestringExhibitor company name.
domainstring or nullExhibitor domain.
descriptionstring or nullExhibitor description.
websitestring or nullWebsite URL.
industrystring or nullIndustry label.
employeeCountinteger or nullEmployee-count snapshot.
countrystring or nullCountry.
logostring or nullLogo URL.
dataSourcestring or nullUpstream data source label.
linkedinUrlstring or nullLinkedIn URL.
fundingRoundstring or nullFunding-round label.
matched_event_idsstring[]For this route, contains the resolved event’s external eventId.
techStacksstring[]Normalized tech-stack names.
categoriesstring[]Optional. Exhibitor categories. Event-scoped when the upstream query is event-scoped. Present only when non-empty.

Response example

{
  "items": [
    {
      "id": "456",
      "companyName": "Acme",
      "domain": "acme.com",
      "description": null,
      "website": "https://acme.com",
      "industry": "Retail Technology",
      "employeeCount": 120,
      "country": "United States",
      "logo": null,
      "dataSource": "vendelux",
      "linkedinUrl": null,
      "fundingRound": null,
      "matched_event_ids": [
        "139574"
      ],
      "techStacks": [
        "React",
        "PostgreSQL"
      ],
      "categories": [
        "Retail",
        "Fintech"
      ]
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when event_id is invalid or list filters fail validation.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the target event cannot be resolved.

Notes

  • Request-side event_id can be either the external event identifier or internal row id, while response-side event references remain in matched_event_ids.

POST /external/exhibitors/search

Authentication

Bearer token required.

Success status code

201 Created

Request body

FieldRequiredTypeNotes
company_urlConditionallystringOptional URL; at least one of company_url or target_audience is required.
target_audienceConditionallystringOptional free-text audience string; at least one of company_url or target_audience is required.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Same exhibitor summary shape as GET /external/exhibitors/list items[].
totalintegerTotal matched exhibitors after the resolver search.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

Response example

{
  "items": [
    {
      "id": "456",
      "companyName": "Acme",
      "domain": "acme.com",
      "description": null,
      "website": "https://acme.com",
      "industry": "Retail Technology",
      "employeeCount": 120,
      "country": "United States",
      "logo": null,
      "dataSource": "vendelux",
      "linkedinUrl": null,
      "fundingRound": null,
      "matched_event_ids": [],
      "techStacks": [
        "React"
      ],
      "categories": [
        "Retail"
      ]
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when neither company_url nor target_audience is provided, or company_url is not a valid URL.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.

Notes

  • No matches return an empty success response rather than 404.
  • company_url is reduced to its hostname with leading www. removed before the runtime builds the domain filter.
  • If both company_url and target_audience are sent, target_audience drives the company-name search string while the extracted domain is still applied as an exact filter.
  • matched_event_ids is an empty array when no event scope or match data exists.
  • techStacks is always returned as an array.

POST /external/exhibitors/search-by-company-name

Authentication

Bearer token required.

Success status code

201 Created

Request body

FieldRequiredTypeNotes
company_nameYesstringPrecision-first exhibitor lookup term.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Same exhibitor summary shape as GET /external/exhibitors/list items[].
totalintegerTotal matched exhibitors for the paged strict search.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

Response example

{
  "items": [
    {
      "id": "456",
      "companyName": "Acme",
      "domain": null,
      "description": null,
      "website": null,
      "industry": "Retail Technology",
      "employeeCount": null,
      "country": null,
      "logo": null,
      "dataSource": null,
      "linkedinUrl": null,
      "fundingRound": null,
      "matched_event_ids": [],
      "techStacks": [],
      "categories": []
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when company_name is empty or invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.

Notes

  • No matches return an empty success response rather than 404.
  • matched_event_ids is an empty array when no event scope or match data exists.
  • techStacks is always returned as an array.

POST /external/exhibitors/search-events

Authentication

Bearer token required.

Success status code

201 Created

Request body

FieldRequiredTypeNotes
company_nameYesstringReverse-lookup source string.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Event summaries enriched with matching exhibitor stubs.
totalintegerTotal matched events.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

items[] fields

FieldTypeNotes
All event summary fieldsobjectSame event summary shape as GET /external/events/list items[].
matchedExhibitorsobject[]Matching exhibitors for this event page row.

items[].matchedExhibitors[] fields

FieldTypeNotes
idstringInternal exhibitor row identifier.
companyNamestringMatching exhibitor company name.

Response example

{
  "items": [
    {
      "id": "123",
      "eventId": "139574",
      "name": "Shoptalk",
      "nickname": null,
      "description": null,
      "url": "https://example.com",
      "dateStart": "2026-03-25",
      "dateEnd": "2026-03-28",
      "venue": "Convention Center",
      "city": "Las Vegas",
      "region": "Nevada",
      "country": "United States",
      "exhibitorCount": 250,
      "image": null,
      "dataSource": "vendelux",
      "matchedExhibitors": [
        {
          "id": "456",
          "companyName": "Acme"
        }
      ]
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when company_name is empty or invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.

Notes

  • No matches return an empty success response rather than 404.
  • Short queries stay exact-only after normalization; longer queries use strict token and prefix admission instead of permissive substring matching.

GET /external/exhibitors/profile

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
exhibitor_idYesstringNumeric-string exhibitor identifier.

Response body

Top-level fields

FieldTypeNotes
idstringInternal exhibitor row identifier.
companyNamestringExhibitor company name.
domainstring or nullExhibitor domain.
descriptionstring or nullExhibitor description.
websitestring or nullWebsite URL.
industrystring or nullIndustry label.
employeeCountinteger or nullEmployee-count snapshot.
countrystring or nullCountry.
logostring or nullLogo URL.
dataSourcestring or nullUpstream data source label.
linkedinUrlstring or nullLinkedIn URL.
fundingRoundstring or nullFunding-round label.
matched_event_idsstring[]Empty unless explicit match scope is attached to the source object.
categoriesstring[]Optional. Exhibitor categories. Present only when non-empty.
eventsobject[]First page of associated events, limited to 20 rows.

events[] fields

FieldTypeNotes
idstringInternal event row identifier.
eventIdstringExternal event identifier.
namestringEvent name.

Response example

{
  "id": "456",
  "companyName": "Acme",
  "domain": "acme.com",
  "description": null,
  "website": "https://acme.com",
  "industry": "Retail Technology",
  "employeeCount": 120,
  "country": "United States",
  "logo": null,
  "dataSource": "vendelux",
  "linkedinUrl": null,
  "fundingRound": null,
  "matched_event_ids": [],
  "categories": [
    "Retail"
  ],
  "events": [
    {
      "id": "123",
      "eventId": "139574",
      "name": "Shoptalk"
    }
  ]
}

Error responses

  • 400 Bad Request when exhibitor_id is not a valid numeric string.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the exhibitor cannot be resolved.

Notes

  • matched_event_ids is an empty array when no event scope or match data exists.
  • The embedded events array is not paginated; it is populated from the first 20 associated events only.

GET /external/exhibitors/events

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
exhibitor_idYesstringNumeric-string exhibitor identifier.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Same event summary shape as GET /external/events/list items[].
totalintegerTotal associated events.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

Response example

{
  "items": [
    {
      "id": "123",
      "eventId": "139574",
      "name": "Shoptalk",
      "nickname": null,
      "description": null,
      "url": "https://example.com",
      "dateStart": "2026-03-25",
      "dateEnd": "2026-03-28",
      "venue": "Convention Center",
      "city": "Las Vegas",
      "region": "Nevada",
      "country": "United States",
      "exhibitorCount": 250,
      "image": null,
      "dataSource": "vendelux"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when exhibitor_id is not a valid numeric string.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the exhibitor cannot be resolved.

Notes

  • Request-side exhibitor_id is snake_case, while response-side identifiers remain id and eventId.

GET /external/personnel/list

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
event_idYesstringSupports either external Event.eventId or internal Event.id.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.
exhibitor_idNostringOptional numeric-string exhibitor filter.
departmentNostringCase-insensitive department filter.
levelNostringCase-insensitive management-level filter.
search_queryNostringMatches relation position or personnel full name.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Personnel contact summaries for the event.
totalintegerTotal distinct personnel matches.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

items[] fields

FieldTypeNotes
idstringInternal personnel row identifier.
fullNamestringFull name.
titlestring or nullFor this route, sourced from personnel.bio.
departmentstring or nullDepartment value.
seniorityLevelstring or nullSeniority or level value.
linkedinUrlstring or nullLinkedIn URL.
companyNamestring or nullAssociated exhibitor company name.
sourceTypestring or nullSource label.

Response example

{
  "items": [
    {
      "id": "789",
      "fullName": "Jane Doe",
      "title": "VP Marketing",
      "department": "Marketing",
      "seniorityLevel": "vp",
      "linkedinUrl": "https://linkedin.com/in/jane-doe",
      "companyName": "Acme",
      "sourceType": "exhibitor"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when event_id or exhibitor_id is invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the target event cannot be resolved.

Notes

  • Request-side identifiers use event_id and optional exhibitor_id, while response-side identifiers use only id.
  • search_query matches either relation position text or personnel fullName.

GET /external/personnel/profile

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
personnel_idYesstringNumeric-string personnel identifier.

Response body

Top-level fields

FieldTypeNotes
idstringInternal personnel row identifier.
fullNamestringFull name.
titlestring or nullSourced from personnel.bio.
departmentstring or nullDepartment value.
seniorityLevelstring or nullSeniority or level value.
linkedinUrlstring or nullLinkedIn URL.
companyNamestring or nullLatest current exhibitor association, if any.
sourceTypestring or nullSource label.

Response example

{
  "id": "789",
  "fullName": "Jane Doe",
  "title": "VP Marketing",
  "department": "Marketing",
  "seniorityLevel": "vp",
  "linkedinUrl": "https://linkedin.com/in/jane-doe",
  "companyName": "Acme",
  "sourceType": "exhibitor"
}

Error responses

  • 400 Bad Request when personnel_id is not a valid numeric string.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the personnel row cannot be resolved.

Notes

  • Request-side personnel_id differs from the response-side id field.

GET /external/personnel/events/by-linkedin

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
linkedin_urlYesstringMust normalize to a valid LinkedIn profile URL. Query strings, fragments, and trailing slashes are ignored during matching.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
personnelobjectSame personnel profile shape as GET /external/personnel/profile.
eventsobjectSame paginated event-list shape as GET /external/personnel/events.

personnel fields

FieldTypeNotes
idstringInternal personnel row identifier.
fullNamestringFull name.
titlestring or nullSourced from personnel.bio.
departmentstring or nullDepartment value.
seniorityLevelstring or nullSeniority or level value.
linkedinUrlstring or nullLinkedIn URL.
companyNamestring or nullLatest current exhibitor association, if any.
sourceTypestring or nullSource label.

events fields

FieldTypeNotes
itemsobject[]Same event summary shape as GET /external/events/list items[].
totalintegerTotal distinct associated events.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

Response example

{
  "personnel": {
    "id": "789",
    "fullName": "Jane Doe",
    "title": "VP Marketing",
    "department": "Marketing",
    "seniorityLevel": "vp",
    "linkedinUrl": "https://linkedin.com/in/jane-doe",
    "companyName": "Acme",
    "sourceType": "exhibitor"
  },
  "events": {
    "items": [
      {
        "id": "123",
        "eventId": "139574",
        "name": "Shoptalk",
        "nickname": null,
        "description": null,
        "url": "https://example.com",
        "dateStart": "2026-03-25",
        "dateEnd": "2026-03-28",
        "venue": "Convention Center",
        "city": "Las Vegas",
        "region": "Nevada",
        "country": "United States",
        "exhibitorCount": 250,
        "image": null,
        "dataSource": "vendelux"
      }
    ],
    "total": 1,
    "page": 1,
    "pageSize": 20,
    "totalPages": 1,
    "hasMore": false
  }
}

Error responses

  • 400 Bad Request when linkedin_url is missing or does not normalize to a valid LinkedIn profile URL.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when no personnel row can be resolved from the normalized LinkedIn URL.

Notes

  • Runtime matching normalizes the URL to https://linkedin.com/in/<slug> form before lookup.
  • If the personnel row exists but has no exhibitor associations, events returns an empty paginated success response instead of 404.

GET /external/personnel/events

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
personnel_idYesstringNumeric-string personnel identifier.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Same event summary shape as GET /external/events/list items[].
totalintegerTotal distinct associated events.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

Response example

{
  "items": [
    {
      "id": "123",
      "eventId": "139574",
      "name": "Shoptalk",
      "nickname": null,
      "description": null,
      "url": "https://example.com",
      "dateStart": "2026-03-25",
      "dateEnd": "2026-03-28",
      "venue": "Convention Center",
      "city": "Las Vegas",
      "region": "Nevada",
      "country": "United States",
      "exhibitorCount": 250,
      "image": null,
      "dataSource": "vendelux"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when personnel_id is not a valid numeric string.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the personnel row cannot be resolved.

Notes

  • If the personnel row exists but has no exhibitor associations, the route returns an empty paginated success response instead of 404.

GET /external/contacts/search

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
company_nameYesstringCompany lookup term.
roleNostringOptional position or role filter.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Same contact summary shape as GET /external/personnel/list items[].
totalintegerTotal distinct personnel matches.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.

Response example

{
  "items": [
    {
      "id": "789",
      "fullName": "Jane Doe",
      "title": "VP Marketing",
      "department": "Marketing",
      "seniorityLevel": "vp",
      "linkedinUrl": "https://linkedin.com/in/jane-doe",
      "companyName": "Acme",
      "sourceType": "exhibitor"
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when company_name is empty or invalid.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.

Notes

  • Request-side company_name is snake_case, while response-side fields are camelCase.
  • Short company queries use a direct contains-style fallback; longer company queries use scored matching.
  • Results are scoped to the authenticated user because the service computes user-specific reveal and task state before mapping the response.

POST /external/profile-matching/recommendations/events/paged

Authentication

Bearer token required.

Success status code

201 Created

Request body

FieldRequiredTypeNotes
company_urlConditionallystringOptional public http(s) URL. At least one of company_url or target_audience is required.
target_audienceConditionallystringOptional audience description. At least one of company_url or target_audience is required.
timeout_msNointegerOptional synchronous onboarding timeout, min 60000, max 3600000.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.
cityNostringExact city filter.
regionNostringExact region filter.
countryNostringExact country filter.
categoryNostring[]Category filters; accepts an array or a comma-separated string.
eventTypeIdsNointeger[]Event type filters; accepts an array or a comma-separated string.
dateStartFromNoYYYY-MM-DD stringLower date bound.
dateStartToNoYYYY-MM-DD stringUpper date bound.
futureNointegerFuture-only flag.
attendeeCountMinNointegerMinimum attendee count.
attendeeCountMaxNointegerMaximum attendee count.

Response body

Top-level fields

FieldTypeNotes
statusstringOne of processing, failed, completed_empty, or completed.
itemsobject[]Recommended events for the current page.
totalintegerTotal merged recommended events after filtering.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.
condition_tagsobjectStructured filter conditions for downstream rendering.
parsed_filters_snapshotobject, optionalParsed filter snapshot, when available.
relaxed_conditionsobject, optionalCurrently used for relaxed-matching metadata.
profile_versionintegerCurrent profile version.
active_result_versioninteger or nullActive recommendation snapshot version.
is_stalebooleantrue when recalculation is in progress over an older active snapshot.
empty_reasonstring, optionalEmpty-result reason when status is empty or failed.
failed_filtersstring[], optionalFilters that did not match.
candidate_countinteger, optionalCandidate count before semantic matching.
suggestionsstring[], optionalSuggested filter adjustments.

items[] fields

FieldTypeNotes
idintegerInternal event row identifier.
eventIdstringExternal event identifier.
namestring or nullEvent name.
nicknamestring or nullEvent short name.
descriptionstring or nullEvent description.
urlstring or nullEvent website URL.
dateStartYYYY-MM-DD string or nullStart date.
dateEndYYYY-MM-DD string or nullEnd date.
venuestring or nullVenue name.
citystring or nullCity.
regionstring or nullRegion or state.
countrystring or nullCountry.
latitudestring or nullLatitude rendered as a string.
longitudestring or nullLongitude rendered as a string.
attendeeCountintegerAttendance count.
declaredExpectedAttendeesintegerDeclared attendance expectation.
estimatedExpectedAttendeesstring or nullEstimated attendance expectation rendered as a string.
priceLowerstring or nullLower ticket price rendered as a string.
priceUpperstring or nullUpper ticket price rendered as a string.
eventTypestring or nullPrimary event-type label.
categoriesobject[]Category metadata.
topicsstring[]Topic list.
topicsCountintegerTopic count.
verifiedintegerVerification flag.
futureintegerFuture-event flag.
historicintegerHistoric-event flag.
historicEventstring or nullHistoric event marker.
imagestring or nullImage URL.
dataSourcestring or nullUpstream data source label.
exhibitorCountintegerExhibitor count.
personnelCountintegerPersonnel count.
eventTypesobject[]Event-type rows.
createTimeinteger-like valueMillisecond timestamp from the event row.
updateTimeinteger-like valueMillisecond timestamp from the event row.
unlockedbooleanUser-specific unlock flag.
matched_exhibitor_countintegerNumber of matched exhibitors at the event.
match_scorenumberRaw profile recommendation score after runtime numeric coercion.

Response example

{
  "status": "completed",
  "items": [
    {
      "id": 123,
      "eventId": "139574",
      "name": "Shoptalk",
      "nickname": null,
      "description": null,
      "url": "https://example.com",
      "dateStart": "2026-03-25",
      "dateEnd": "2026-03-28",
      "venue": "Convention Center",
      "city": "Las Vegas",
      "region": "Nevada",
      "country": "United States",
      "latitude": null,
      "longitude": null,
      "attendeeCount": 10000,
      "declaredExpectedAttendees": 0,
      "estimatedExpectedAttendees": null,
      "priceLower": null,
      "priceUpper": null,
      "eventType": null,
      "categories": [],
      "topics": [],
      "topicsCount": 0,
      "verified": 1,
      "future": 1,
      "historic": 0,
      "historicEvent": null,
      "image": null,
      "dataSource": "vendelux",
      "exhibitorCount": 250,
      "personnelCount": 1800,
      "eventTypes": [],
      "createTime": 1711000000000,
      "updateTime": 1711000000000,
      "unlocked": false,
      "matched_exhibitor_count": 12,
      "match_score": 0.82
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false,
  "condition_tags": {},
  "profile_version": 3,
  "active_result_version": 3,
  "is_stale": false
}

Error responses

  • 400 Bad Request when the body fails validation.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 409 Conflict when a recommendation task is already running for the user.

Notes

  • The route runs synchronous apply-onboarding first, then returns the current paged recommendation snapshot.
  • Paging is applied after the service merges duplicate recommendation rows by event.
  • Top-level metadata includes status, condition_tags, profile_version, active_result_version, and is_stale; empty-result responses may also include empty_reason, failed_filters, candidate_count, and suggestions.
  • match_score here is the raw recommendation score; POST /external/events/fit-score separately normalizes a score onto a 0-10 style scale.

GET /external/profile-matching/recommendations/exhibitors

Authentication

Bearer token required.

Success status code

200 OK

Query parameters

NameRequiredTypeNotes
event_idYesstringSupports either external Event.eventId or internal Event.id.
pageNointegerDefaults to 1.
pageSizeNointegerDefaults to 20, max 100.
locationNostringCountry or location filter.
searchQueryNostringSearch term over company name or description.
exhibitorNameNostring[]Exact exhibitor-name filter; repeated query params or a single value become an array.
categoryNostring[]Category-name filter; repeated query params or a single value become an array.
industryNostring[]Industry-name filter; repeated query params or a single value become an array.
employeesMinNointegerMinimum employee count.
employeesMaxNointegerMaximum employee count.

Response body

Top-level fields

FieldTypeNotes
itemsobject[]Recommended exhibitors for the resolved event.
totalintegerTotal exhibitors after filtering.
pageintegerCurrent page number.
pageSizeintegerPage size used at runtime.
totalPagesinteger0 when total is 0.
hasMorebooleantrue when another page exists.
codestring, optionalPresent only for fallback responses; currently AI_SEARCH_RESULT_MISMATCH.
show_refresh_hintboolean, optionalPresent only for fallback responses.

items[] fields

FieldTypeNotes
idstringInternal exhibitor row identifier.
companyNamestringExhibitor company name.
descriptionstring or nullExhibitor description.
logostring or nullLogo URL.
websitestring or nullWebsite URL.
countrystring or nullCountry.
industrystring or nullIndustry label.
categoriesstring[]Event-scoped business tags.
employeeCountinteger or nullEmployee-count snapshot.
companySizestring or nullRaw company_size value.
fundingRoundstring or nullFunding-round label.
techStacksstring[]Normalized tech-stack names.

Response example

{
  "items": [
    {
      "id": "456",
      "companyName": "Acme",
      "description": null,
      "logo": null,
      "website": "https://acme.com",
      "country": "United States",
      "industry": "Retail Technology",
      "categories": [
        "Commerce"
      ],
      "employeeCount": 120,
      "companySize": "51-200",
      "fundingRound": null,
      "techStacks": [
        "React"
      ]
    }
  ],
  "total": 1,
  "page": 1,
  "pageSize": 20,
  "totalPages": 1,
  "hasMore": false
}

Error responses

  • 400 Bad Request when event_id is invalid or filters fail validation.
  • 401 Unauthorized when the API key is missing, malformed, or invalid.
  • 404 Not Found when the target event cannot be resolved.

Notes

  • Request-side event_id differs from the response-side id field on exhibitors.
  • The route may return fallback metadata at the top level: code: "AI_SEARCH_RESULT_MISMATCH" and show_refresh_hint: true.
  • In fallback mode, items.length may be smaller than pageSize even when hasMore is true because stored recommended exhibitor ids can resolve to deleted or missing exhibitor rows.
  • techStacks is always returned as an array.