Skip to main content
POST
Match Users
Ranks other users against an asker’s interests, using activity-derived interest facets — clusters of what each user has actually engaged with over time, not a static profile. The endpoint returns a structured match breakdown (who, how strongly, and on which facets), optionally with sample content that illustrates each overlap. Matching runs in two modes:
  • passive — match against the asker’s own interest facets. Answers “who is like me?” No free-text; the asker’s top facets are the query.
  • directed — match against a free-text query topic. Answers “who is into biotech?” The query is embedded and ranked against candidate facets.
Requires a paid plan, the ai-search bundle, the interest-matching bundle, and interestMatching.enabled set on the project. See the Interest Matching guide for setup.

Authentication

The endpoint uses optional user auth, but each mode enforces its own requirement in the controller:
  • passive requires an identified user (the asker) — their facets are the query. No user → 401.
  • directed also requires an identified user. A bare client token with no user session → 401.

Body Parameters

mode
string
required
"passive" or "directed".
query
string
The free-text topic to match against. Required in directed mode; rejected in passive mode.
limit
number
default:"20"
Maximum number of matched users to return. Maximum 50.
spaceId
string
Restrict candidates to users active in this space.
includeChildSpaces
boolean
default:"false"
Only applies with spaceId. When true, candidates active anywhere in the space’s subtree are eligible. Ignored without spaceId.
includeSampleContent
boolean
default:"false"
Gate 2 of the two-gate sample exposure. When true and the project setting interestMatching.exposeSampleContent is on, each matched facet includes a few illustrative content snippets from the candidate. Requesting samples while the project setting is off returns 403 match/sample-content-disabled.
excludeSelf
boolean
default:"true"
Exclude the asker from the results.

Response

Returns the { results: [...] } envelope (a deliberate divergence from search/*, which return bare arrays). Results are ordered by descending score.
Breakdown fields
  • score — the aggregate match score. In passive mode this is additive over the top matched facet-pairs (two moderate overlaps can outrank one very strong overlap); in directed mode it is the single best facet’s similarity · weight(hotness).
  • matchedFacets[].similarity — cosine similarity of the facet pair.
  • matchedFacets[].askerFacet — the asker’s side of the pair. Present in passive mode; omitted in directed mode (there is no asker facet — the query is the anchor) and for the cold-start bio fallback.
  • matchedFacets[].candidateFacet — the candidate’s facet: its id and lazily-decayed hotness.
  • matchedFacets[].sampleContent — present only when both sample gates are satisfied. Never contains moderation-removed, soft-deleted, or private-DM content.
The always-returned breakdown (users, scores, facet ids, similarities, hotness) carries no readable content — raw content appears only behind the two gates.

Cold-start fallback

In passive mode, if the asker has no facet above the significance threshold, the endpoint falls back to the asker’s bio embedding (from UserEmbeddings) as a single pseudo-facet, so a brand-new user can still get matches. Cold-start matches omit askerFacet on the breakdown.

Candidate exclusions

Candidates are excluded when they are: the asker (unless excludeSelf: false), users with an active suspension (a future-dated suspension does not count as active), and — for a space-scoped match — users banned in that space.

Error Responses

The interest-matching bundle is not installed.