Identity & Members

Profiles Service

The Profiles service manages user profiles in the biztechProfiles DynamoDB table. Profiles are created during membership grant or manually via POST /profiles. Handlers are in services/profiles/handler.js.


Endpoints

MethodPathAuthHandlerDescription
POST/profilesCognitocreateCreate profile for current user
GET/profiles/profile/{profileID}PublicgetPublicProfileGet public-facing profile
GET/profiles/user/CognitogetUserProfileGet current user's full profile
PATCH/profiles/user/CognitoupdatePublicProfileUpdate profile fields / visibility
POST/profiles/profile-pic-upload-urlCognitocreateProfilePicUploadUrlGet presigned S3 upload URL

Deprecated endpoints

These exist in the handler but are no longer part of the core product flow:

MethodPathHandlerDescription
POST/profiles/partner/partialcreatePartialPartnerProfileCreate partner profile + NFC
POST/profiles/companycreateCompanyProfileCreate company profile + QR
POST/profiles/company/link-partnerlinkPartnerToCompanyLink partner to a company
POST/profiles/sync-partner-datasyncPartnerDataBulk sync partner profiles

Table Structure

Table: biztechProfiles (constant PROFILES_TABLE). Composite key:

KeyAttributeValue
PKcompositeIDPROFILE#<profileID> where profileID is a human-readable ID
SKtypePROFILE for profile records, CONNECTION#<id> for connection records

The profileID is generated by the human-id library (e.g. SillyPandasDeny). Connection records share this table — see Connections for details.


Profile Types

The profileType field is set at creation:

TypeAssigned when
EXECCreator's email ends with @ubcbiztech.com
ATTENDEEAll other users
PARTNERSet via deprecated createPartialPartnerProfile endpoint

POST /profiles — Create Profile

Creates a profile for the authenticated user. Uses the email from the Cognito JWT claims.

Behavior:

  1. Looks up the user in biztechMembers2026 by email
  2. Generates a profileID using human-id
  3. Creates a profile record with default viewableMap (all optional fields hidden)
  4. Updates the member record with a link to the new profile

No request body is needed — fname, lname, pronouns, year, major are read from the member record.

Automatic creation

Profiles are also created automatically during membership grant (POST /members/grant) and during payment webhook processing. Direct POST /profiles is mainly needed for exec self-enrollment.


GET /profiles/profile/{profileID} — Public Profile

Returns only the profile fields the user has marked as visible in their viewableMap.

Always returned: profileType, fname, lname, pronouns, year, major

Conditionally returned (based on viewableMap):

  • hobby1, hobby2
  • funQuestion1, funQuestion2
  • linkedIn
  • profilePictureURL
  • additionalLink
  • description

No authentication required. This is the endpoint used to display profiles on the companion app and live wall.


GET /profiles/user/ — Full Profile

Returns the complete profile for the authenticated user, including all fields and the viewableMap. Requires Cognito auth.

The response includes every field on the profile record:

{
  "profileType": "ATTENDEE",
  "fname": "Kevin",
  "lname": "Xiao",
  "pronouns": "He/Him",
  "year": "3rd Year",
  "major": "BUCS",
  "hobby1": "",
  "hobby2": "",
  "funQuestion1": "",
  "funQuestion2": "",
  "linkedIn": "",
  "profilePictureURL": "",
  "additionalLink": "",
  "description": "",
  "viewableMap": {
    "fname": true,
    "lname": true,
    "pronouns": true,
    "year": true,
    "major": true,
    "hobby1": false,
    "hobby2": false,
    "funQuestion1": false,
    "funQuestion2": false,
    "linkedIn": false,
    "profilePictureURL": false,
    "additionalLink": false,
    "description": false
  },
  "compositeID": "PROFILE#SillyPandasDeny",
  "type": "PROFILE",
  "createdAt": 1754072664036,
  "updatedAt": 1754072664036
}

PATCH /profiles/user/ — Update Profile

Updates mutable profile attributes and/or visibility settings. Requires Cognito auth.

Mutable attributes (defined in MUTABLE_PROFILE_ATTRIBUTES): hobby1, hobby2, funQuestion1, funQuestion2, linkedIn, profilePictureURL, additionalLink, description

Fields like fname, lname, pronouns, year, major are not updatable through this endpoint — they come from the member record.

Request body:

{
  "viewableMap": { "description": true },
  "description": "Testing description"
}

The viewableMap field is required in the body (at minimum an empty object {}). Only the keys you include will be updated — omitted keys keep their current values.


POST /profiles/profile-pic-upload-url — Profile Picture Upload

Generates a presigned S3 URL for uploading a profile picture. Requires Cognito auth.

Request body:

FieldRequiredDescription
fileTypeYesMIME type (must start with image/)
fileNameYesOriginal file name
prefixNoSubfolder prefix (defaults to profile-photos)

Optionally pass profileId as a query parameter — if omitted, uses the authenticated user's profile.

Response:

{
  "uploadUrl": "https://s3...presigned-url",
  "key": "profile-pictures/SillyPandasDeny/profile-photos/1735689600000.jpg",
  "publicUrl": "https://bucket.s3.region.amazonaws.com/profile-pictures/..."
}

The presigned URL expires after 60 seconds.


Key Files

FilePurpose
services/profiles/handler.jsAll endpoint handlers
services/profiles/helpers.jscreateProfile, filterPublicProfileFields, buildProfileUpdateParams
services/profiles/constants.jsMUTABLE_PROFILE_ATTRIBUTES, PROFILE_TYPES, TYPES


Previous
Members Service