useLoyalty
Server SDK

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/members

Request 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

FieldTypeRequiredDescription
externalIdstringYesYour unique identifier for this user
emailstringNoMember's email address
namestringNoDisplay name
avatarUrlstringNoProfile image URL
phonestringNoPhone number
dateOfBirthstringNoISO date (YYYY-MM-DD)
metadataobjectNoCustom 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_123

Exactly 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/:externalId

SDK

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/members

Query Parameters

ParameterTypeDefaultDescription
searchstring-Search by externalId, email, or name
limitnumber50Results per page (max 100)
offsetnumber0Number 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/:externalId

Response

{
  "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/:externalId

Request 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/:externalId

This 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 PointsLevel
0-991
100-3992
400-8993
900-15994
1600-24995

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.

On this page