On this page

Follows represent a follow relationship between two users. Creating follows is easy. Simply pass in the `id` or the `username` of the user creating the follow (i.e. the follower) into the `startId` field, and `id` or the `username` of the follow recipient (i.e. the followee) into the `endId` field. Use the same id you used when creating the profile.

You can use either the socialfi package (recommended for easier integration) or call the API directly.

## Installing and Setting Up the Socialfi Package (Recommended)

We recommend using the socialfi package as it simplifies API interactions:

```bash
npm install socialfi
```

```ts
import { SocialFi } from 'socialfi';

const API_URL = 'https://api.usetapestry.dev/v1/'; // tapestry prod URL
// const API_URL = 'https://api.dev.usetapestry.dev/v1/'; // tapestry dev URL

const API_KEY = process.env.TAPESTRY_API_KEY; // Get your API key from https://app.usetapestry.dev/

const client = new SocialFi({
  baseURL: API_URL,
  apiKey: API_KEY,
});
```

Here's an example command that makes user `marcus` follow user `nehemiah`.

### Using the Socialfi Package

```ts
// Make 'marcus' follow 'nehemiah'
try {
  const followResult = await client.followers.postFollowers(
    {
      apiKey: API_KEY
    },
    {
      startId: 'marcus',
      endId: 'nehemiah',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }
  );
  console.log('Follow created successfully:', followResult);
} catch (error) {
  console.error('Error creating follow:', error);
}
```

### Using the API Directly

```ts
// Make 'marcus' follow 'nehemiah'
try {
  const response = await fetch('https://api.usetapestry.dev/v1/followers?apiKey=YOUR_API_KEY', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      startId: 'marcus',
      endId: 'nehemiah',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }),
  });

const followResult = await response.json();
  console.log('Follow created successfully:', followResult);
} catch (error) {
  console.error('Error creating follow:', error);
}
```

## Checking Follow Status

To check if the follow succeeded, you can GET the followers count of the user who received the follow. In this example, we'll ask for `nehemiah`'s followers count:

### Using the Socialfi Package

```ts
// Get nehemiah's follower count
try {
  const followerCountData = await client.followers.getFollowersCount(
    {
      apiKey: API_KEY,
      profileId: 'nehemiah'
    }
  );
  console.log(`nehemiah has ${followerCountData.count} followers`);
} catch (error) {
  console.error('Error fetching follower count:', error);
}
```

### Using the API Directly

```ts
// Get nehemiah's follower count
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/followers/nehemiah/count?apiKey=YOUR_API_KEY'
  );
  const followerCountData = await response.json();
  console.log(`nehemiah has ${followerCountData.count} followers`);
} catch (error) {
  console.error('Error fetching follower count:', error);
}
```

and you can also check the following count of the user who performed the follow. In this example, we'll ask for `marcus`'s following count:

### Using the Socialfi Package

```ts
// Get marcus's following count
try {
  const followingCountData = await client.followers.getFollowingCount(
    {
      apiKey: API_KEY,
      profileId: 'marcus'
    }
  );
  console.log(`marcus is following ${followingCountData.count} users`);
} catch (error) {
  console.error('Error fetching following count:', error);
}
```

### Using the API Directly

```ts
// Get marcus's following count
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/following/marcus/count?apiKey=YOUR_API_KEY'
  );
  const followingCountData = await response.json();
  console.log(`marcus is following ${followingCountData.count} users`);
} catch (error) {
  console.error('Error fetching following count:', error);
}
```

## Unfollowing Users

To unfollow a user, you can use the unfollow endpoint:

### Using the Socialfi Package

```ts
// Make 'marcus' unfollow 'nehemiah'
try {
  const unfollowResult = await client.followers.deleteFollower(
    {
      apiKey: API_KEY
    },
    {
      startId: 'marcus',
      endId: 'nehemiah',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }
  );
  console.log('Unfollow successful:', unfollowResult);
} catch (error) {
  console.error('Error unfollowing user:', error);
}
```

### Using the API Directly

```ts
// Make 'marcus' unfollow 'nehemiah'
try {
  const response = await fetch('https://api.usetapestry.dev/v1/followers?apiKey=YOUR_API_KEY', {
    method: 'DELETE',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      startId: 'marcus',
      endId: 'nehemiah',
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }),
  });

const unfollowResult = await response.json();
  console.log('Unfollow successful:', unfollowResult);
} catch (error) {
  console.error('Error unfollowing user:', error);
}
```

## Getting Follow Lists

You can retrieve lists of followers and following users:

### Get Followers List

#### Using the Socialfi Package

```ts
try {
  const followers = await client.followers.getFollowers(
    {
      apiKey: API_KEY,
      profileId: 'nehemiah',
      limit: 20,
      offset: 0
    }
  );
  console.log('Nehemiah's followers:', followers);
} catch (error) {
  console.error('Error fetching followers:', error);
}
```

#### Using the API Directly

```ts
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/followers/nehemiah?apiKey=YOUR_API_KEY&limit=20&offset=0'
  );
  const followers = await response.json();
  console.log('Nehemiah's followers:', followers);
} catch (error) {
  console.error('Error fetching followers:', error);
}
```

### Get Following List

#### Using the Socialfi Package

```ts
try {
  const following = await client.followers.getFollowing(
    {
      apiKey: API_KEY,
      profileId: 'marcus',
      limit: 20,
      offset: 0
    }
  );
  console.log('Marcus is following:', following);
} catch (error) {
  console.error('Error fetching following list:', error);
}
```

#### Using the API Directly

```ts
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/profiles/following/marcus?apiKey=YOUR_API_KEY&limit=20&offset=0'
  );
  const following = await response.json();
  console.log('Marcus is following:', following);
} catch (error) {
  console.error('Error fetching following list:', error);
}
```

## Checking Follow Relationships

To check if one user follows another:

### Using the Socialfi Package

```ts
try {
  const followStatus = await client.followers.checkFollowStatus(
    {
      apiKey: API_KEY,
      followerId: 'marcus',
      followeeId: 'nehemiah'
    }
  );
  console.log('Marcus follows Nehemiah:', followStatus.isFollowing);
} catch (error) {
  console.error('Error checking follow status:', error);
}
```

### Using the API Directly

```ts
try {
  const response = await fetch(
    'https://api.usetapestry.dev/v1/followers/check?apiKey=YOUR_API_KEY&followerId=marcus&followeeId=nehemiah'
  );
  const followStatus = await response.json();
  console.log('Marcus follows Nehemiah:', followStatus.isFollowing);
} catch (error) {
  console.error('Error checking follow status:', error);
}
```

### Response Example

```json
{
  "isFollowing": true,
  "followId": "follow-123456789",
  "followedAt": "2024-01-15T10:30:00Z"
}
```

## Bulk Follow Operations

For bulk follow operations, you can follow multiple users at once:

### Using the Socialfi Package

```ts
try {
  const bulkFollowResult = await client.followers.bulkFollow(
    {
      apiKey: API_KEY,
    },
    {
      startId: 'marcus',
      endIds: ['nehemiah', 'alice', 'bob'],
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }
  );
  console.log('Bulk follow results:', bulkFollowResult);
} catch (error) {
  console.error('Error in bulk follow:', error);
}
```

### Using the API Directly

```ts
try {
  const response = await fetch('https://api.usetapestry.dev/v1/followers/bulk?apiKey=YOUR_API_KEY', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      startId: 'marcus',
      endIds: ['nehemiah', 'alice', 'bob'],
      blockchain: 'SOLANA',
      execution: 'FAST_UNCONFIRMED'
    }),
  });

const bulkFollowResult = await response.json();
  console.log('Bulk follow results:', bulkFollowResult);
} catch (error) {
  console.error('Error in bulk follow:', error);
}
```

## Example Response Structures

### Followers/Following List Response

```json
{
  "users": [
    {
      "profile": {
        "id": "marcus",
        "username": "marcus",
        "walletAddress": "ABC123...",
        "customProperties": {
          "bio": "Software developer and crypto enthusiast",
          "profileImage": "https://example.com/marcus.jpg"
        }
      },
      "followRelation": {
        "id": "follow-123456789",
        "createdAt": "2024-01-15T10:30:00Z"
      },
      "socialCounts": {
        "followers": 250,
        "following": 180
      }
    }
  ],
  "pagination": {
    "total": 25,
    "limit": 20,
    "offset": 0,
    "hasMore": true
  }
}
```

### Follow Count Response

```json
{
  "profileId": "nehemiah",
  "count": 25,
  "lastUpdated": "2024-01-15T11:30:00Z"
}
```

## Best Practices

When implementing follow functionality:

- **Mutual Follows**: Consider implementing logic to detect mutual follows for enhanced social features
- **Rate Limiting**: Implement rate limiting to prevent spam following
- **Notifications**: Send notifications when users gain new followers
- **Privacy Settings**: Respect user privacy settings regarding follow visibility
- **Bulk Operations**: Use bulk operations when possible to reduce API calls
- **Error Handling**: Handle cases where users try to follow themselves or follow the same user multiple times
- **UI Feedback**: Provide immediate UI feedback with optimistic updates
- **Follow Suggestions**: Use the social graph to suggest new users to follow
