People API
People is the profile-discovery and mutual-interest surface. It is separate
from friendships: a mutual like creates a match and a direct chat, but does
not create a friendship.
All endpoints require Authorization: Bearer <supabase-access-token>.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /people | Discover completed, visible profiles |
| PATCH | /people/location | Set location sharing mode and position |
| GET | /people/search | Search by partial username |
| GET | /people/:profileId | View a public profile |
| PUT | /people/:profileId/interaction | Save a like or dislike |
| DELETE | /people/:profileId/interaction | Remove the current interaction |
| GET | /people/interactions | List active interactions |
| GET | /people/incoming-likes | List incoming likes |
| GET | /people/matches | List mutual likes and their chats |
| POST | /people/:userId/block | Block a user |
| DELETE | /people/:userId/block | Unblock a user |
| POST | /people/:userId/report | Report a user |
Discovery feed
GET /people?sex=female&ageMin=21&ageMax=35&language=en,ru&limit=12
Authorization: Bearer <token>
The response is { data, nextCursor }. The default page size is 12 and the
maximum is 50. Multi-value filters accept a comma-separated value or repeated
query parameters. Unknown enum values are rejected.
| Query | Description |
|---|---|
ageMin, ageMax | Age, 19..120 |
heightMin, heightMax | Height in cm, 55..272 |
sex | all, male, female |
datingPurpose, education, language, religion | One or more values |
alcohol, smoking, bodyType, familyPlan, wealth, zodiac | One or more values |
distanceMin, distanceMax | Distance in km |
isMapSelection | Only profiles visible on the map |
cursor, limit | Keyset pagination |
The feed excludes the caller, incomplete or hidden profiles, and blocked
users. Public locations are coarsened to approximately a 500 m grid. When
isMapSelection=true, a fresh live point may be returned instead; live points
older than five minutes are treated as stale.
Location sharing
PATCH /people/location
{ "locationSharingMode": "live", "latitude": 43.238, "longitude": 76.945, "city": "Almaty" }
locationSharingMode is disabled, static, or live. Coordinates are
required for the latter two modes. The response contains the mode and
locationUpdatedAt. Map visibility is controlled separately by
isVisibleOnMap on the profile.
Search and profile detail
GET /people/search?q=yakov&limit=20 performs a case-insensitive partial
username search. The @ is optional. Results omit the caller, existing
friends, and blocked users, and include friendshipStatus (none,
pending_outgoing, pending_incoming, or rejected).
GET /people/:profileId returns the public profile shape, including photos,
education, languages, and privacy-filtered dating purpose/zodiac. The path
parameter is a profile ID, not a user ID.
Likes, dislikes, and matches
PUT /people/:profileId/interaction
{ "type": "like" }
Interactions expire after seven days. like and dislike can be removed with
DELETE. A mutual like creates one canonical match and ensures one direct
chat; the response includes isMatch, matchId, and chatId when relevant.
Use /people/incoming-likes and /people/matches with cursor and limit
(default 20, maximum 100) for the corresponding paginated lists.
Reports
The people-specific report endpoint accepts fake_profile,
unacceptable_content, toxic_behavior, incorrect_age,
behavior_outside_social_network, or other, plus an optional description of
250 characters. General user/event/chat reports are documented in Reports.