Two-Sided Matching
Some events are two-sided markets rather than open networking: founders pitch investors, buyers meet sellers, mentees meet mentors. For those events the Partner API can enforce a hard matching boundary: participants on one side are only ever matched with the other side, on every surface where Meshi pairs people — ranked match lists, agent recommendations, and icebreakers. Your app never needs to client-side filter for this.
How sides work
Section titled “How sides work”Each event attendee can carry a side tag: "founder", "investor", or null.
- Tagging any attendee activates the policy for that event. Events where nobody carries a side behave as ordinary open-networking events — every eligible pair can match.
- At a sided event, matching is strictly cross-side: founders match only investors, and vice versa.
- An attendee with no side is unmatchable at a sided event (fail-closed). They receive no matches and appear in no one else’s matches until tagged. This protects the boundary: an untagged person can never leak into the wrong side’s results.
The side vocabulary is fixed (founder / investor) and validated on write; values are
case-sensitive and unknown values are rejected with 400 INVALID_ATTENDEE_SIDE. Use the pair
that best maps to your marketplace — the semantics are generic (“side A only meets side B”).
Setting sides
Section titled “Setting sides”At import — include side on each row of
PUT /events/:event_id/attendees:import.
Every accepted import reapplies side; omitting it or sending null deliberately untags an
existing attendee. Include the side on every re-import unless that is the intended result.
Correcting one side without another import run — PATCH /events/:event_id/attendees/:attendee_id with
{ "side": "investor" } (or "founder", or null to untag). A re-tag automatically discards
the attendee’s existing match scores and queues a re-score, so the next match run reflects the
correction.
Checking coverage
Section titled “Checking coverage”The matching boundary is only as good as your tag coverage. Before opening match browsing,
check GET /events/:event_id/readiness:
its side_coverage object reports whether the policy is active, founder/investor counts,
untagged_count, mapped untagged_attendee_ids, and untagged_entity_ids for the full roster.
Anyone listed there gets no matches until you tag them. If your event is intended to be two-sided,
require policy_active: true; the API cannot infer that intent when every side is omitted.
The top-level warnings array promotes the conditions most likely to make a match run useless:
a missing counterpart side, untagged attendees, a severe side imbalance, or attendees that are not
match-ready. Treat severity: "blocking" as a stop sign. A severe imbalance is advisory, but it
means the smaller side may receive repetitive recommendations and limit match variety.
Event context can improve match quality
Section titled “Event context can improve match quality”Sides decide who may match. Identity and intent decide who matches well. Always send the
stable identity fields you already have, such as email and LinkedIn URL. event_goal is optional
plain-language context; Meshi can derive missing needs and evidence-backed offers from it. If it
is absent, matching falls back to the attendee’s current inferred or confirmed profile intent.
If neither event-specific nor usable global intent exists, readiness reports the missing input and
that attendee may not be match-ready.
Send event_needs or event_offers only when the attendee supplied those directions explicitly.
An explicit axis overrides Meshi’s derived value for that axis. Matching compares needs against
offers in both directions and handles a single available direction without treating the missing
direction as a bad match.
Reading results
Section titled “Reading results”Match queries serve pinned snapshots of the latest terminal match run. After imports,
re-tags, or goal changes, trigger a new
POST /events/:event_id/match-runs to
refresh results.
Each match item carries an explainability object — a calibrated tier plus readable
reasons framed around both sides’ stated needs and offers. Lead your UI with the tier and
reasons rather than raw scores.
To hide people a user has already met (or dismissed), pass exclude_entity_ids[] on the match
queries — applied server-side before pagination, capped at 500 IDs per request. Values may be a
partner attendee ID or an event-roster entity_id; unknown and out-of-event values are ignored.
Pin run_id while paging. If omitted, Meshi uses the latest terminal run.
V1 contract and future matching
Section titled “V1 contract and future matching”The API currently serves V1 matchmaking: heuristic rankings based on complementary needs and evidence-supported offers, alignment, and profile similarity, with categorical tiers and readable reasons. These are useful rankings, not guarantees or scientific probabilities. Future V2 memory-backed and adaptive matching is still in development and is not part of this API contract or required for this integration.
Lifecycle summary
Section titled “Lifecycle summary”- Import attendees with stable identity fields,
side, and any event context you already have; poll the import run. - Check
warnings,side_coverage,match_readiness, andintent_processing; resolve blocking warnings and tag stragglers. Pending intent can use profile fallback, or you can wait when freshness matters. - Trigger a match run → poll to terminal.
- Query matches per attendee; render
tier+reasons; pass exclusions as users meet people. - On roster, side, or intent changes, re-run matching to refresh the snapshot.