Members
Create and manage member profiles in your loyalty program
Members represent the users in your gamification system. Each member has a unique externalId that links to your application's user system.
Create or Update Member
Creates a new member or updates an existing one (upsert behavior).
POST /api/v1/membersRequest Body
{
"externalId": "user_123",
"email": "john@example.com",
"name": "John Doe",
"avatarUrl": "https://example.com/avatar.jpg",
"phone": "+1234567890",
"dateOfBirth": "1990-05-15",
"metadata": {
"plan": "premium",
"signupSource": "mobile"
}
}Parameters
| Field | Type | Required | Description |
|---|---|---|---|
externalId | string | Yes | Your unique identifier for this user |
email | string | No | Member's email address |
name | string | No | Display name |
avatarUrl | string | No | Profile image URL |
phone | string | No | Phone number |
dateOfBirth | string | No | ISO date (YYYY-MM-DD) |
metadata | object | No | Custom key-value data |
Response
{
"id": "clx123abc",
"externalId": "user_123",
"email": "john@example.com",
"name": "John Doe",
"points": 0,
"totalPointsEarned": 0,
"createdAt": "2024-01-15T10:30:00Z"
}Find Member
Look up a member by email, phone, or externalId — useful when you don't have the externalId on hand.
GET /api/v1/members/lookup?email=john@example.com
GET /api/v1/members/lookup?phone=%2B14155550100
GET /api/v1/members/lookup?externalId=user_123Exactly one query parameter must be provided.
SDK
// by email
const member = await useLoyalty.members.find({ email: "john@example.com" });
// by phone
const member = await useLoyalty.members.find({ phone: "+14155550100" });
// by externalId (same as members.get but consistent interface)
const member = await useLoyalty.members.find({ externalId: "user_123" });Response
Returns a full Member object.
TypeScript users: MemberLookupInput is a discriminated union — passing zero
identifiers or mixing two is a compile error, not a runtime failure.
Upsert Member
Create a member if they don't exist, update if they do. Useful as a one-shot sync on every login.
PUT /api/v1/members/:externalIdSDK
const member = await useLoyalty.members.upsert({
externalId: user.id,
email: user.email,
name: user.name,
});List Members
Retrieve members with optional filtering and pagination.
GET /api/v1/membersQuery Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
search | string | - | Search by externalId, email, or name |
limit | number | 50 | Results per page (max 100) |
offset | number | 0 | Number of results to skip |
Example
curl -X GET "https://app.useloyalty.app/api/v1/members?search=john&limit=20" \
-H "Authorization: Bearer sk_your_key"Response
{
"members": [
{
"id": "clx123abc",
"externalId": "user_123",
"email": "john@example.com",
"name": "John Doe",
"points": 1500,
"totalPointsEarned": 2500,
"createdAt": "2024-01-15T10:30:00Z"
}
],
"pagination": {
"total": 1,
"limit": 20,
"offset": 0
}
}Get Member
Retrieve a specific member by their external ID.
GET /api/v1/members/:externalIdResponse
{
"id": "clx123abc",
"externalId": "user_123",
"email": "john@example.com",
"name": "John Doe",
"avatarUrl": "https://example.com/avatar.jpg",
"points": 1500,
"totalPointsEarned": 2500,
"currentStreak": 5,
"longestStreak": 12,
"metadata": {
"plan": "premium"
},
"badges": [
{
"id": "badge_1",
"name": "Early Adopter",
"imageUrl": "https://...",
"awardedAt": "2024-01-20T00:00:00Z"
}
],
"rewardsCount": 3,
"questCompletionsCount": 15,
"createdAt": "2024-01-15T10:30:00Z"
}Update Member
Update an existing member's profile.
PATCH /api/v1/members/:externalIdRequest Body
{
"name": "John Smith",
"email": "john.smith@example.com",
"metadata": {
"plan": "enterprise"
}
}Response
Returns the updated member object.
Delete Member
Permanently delete a member and their associated data.
DELETE /api/v1/members/:externalIdThis action is irreversible. All member data including points, badges, and quest completions will be permanently deleted.
Response
{
"success": true,
"message": "Member deleted successfully"
}Code Examples
Create Member on Signup
// When a user signs up in your app
async function onUserSignup(user: User) {
await fetch("https://app.useloyalty.app/api/v1/members", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.USELOYALTY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
externalId: user.id,
email: user.email,
name: user.name,
metadata: {
signupDate: new Date().toISOString(),
source: "web",
},
}),
});
}Sync Member Profile
// Keep member profile in sync with your user data
async function syncMemberProfile(userId: string, updates: Partial<User>) {
await fetch(`https://app.useloyalty.app/api/v1/members/${userId}`, {
method: "PATCH",
headers: {
Authorization: `Bearer ${process.env.USELOYALTY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: updates.name,
email: updates.email,
avatarUrl: updates.avatar,
}),
});
}Check Member Exists
async function getMemberOrCreate(userId: string, userData: User) {
const response = await fetch(
`https://app.useloyalty.app/api/v1/members/${userId}`,
{
headers: {
Authorization: `Bearer ${process.env.USELOYALTY_API_KEY}`,
},
},
);
if (response.status === 404) {
// Member doesn't exist, create them
return createMember(userId, userData);
}
return response.json();
}Member Tiers & Segments
The member object now includes tier and segment membership:
{
"externalId": "user_123",
"points": 4200,
"referralCode": "JOHN-ABC123",
"tier": {
"id": "tier_gold",
"name": "Gold",
"level": 3,
"minPoints": 3000,
"color": "#FFD700"
},
"segments": ["vip", "early-adopter"]
}See Tiers for assigning and managing member tiers.
Member Levels
Members have a calculated level based on their total points earned:
Level = floor(sqrt(totalPointsEarned / 100)) + 1| Total Points | Level |
|---|---|
| 0-99 | 1 |
| 100-399 | 2 |
| 400-899 | 3 |
| 900-1599 | 4 |
| 1600-2499 | 5 |
The level is calculated automatically and returned in the member response.
Metadata Best Practices
Use metadata to store custom data relevant to your application:
{
"metadata": {
"subscription_tier": "premium",
"preferred_language": "en",
"signup_campaign": "summer_2024",
"custom_attributes": {
"department": "engineering"
}
}
}Metadata is stored as JSON and can contain nested objects. Maximum size is 16KB.