---
title: "Social Graph API"
description: "Social graph API — developer connections, influence scoring, and network analysis"
canonical: "https://docs.ainative.studio/docs/community/social-graph"
last-updated: "2026-10-22T17:48:46.689Z"
---

# Social Graph API

Source: https://docs.ainative.studio/docs/community/social-graph

> Social graph API — developer connections, influence scoring, and network analysis

# Social Graph API

The Social Graph API lets you build follower networks, bidirectional friendships, and user moderation (block/ignore) on top of AINative community data.

**Base path:** `https://api.ainative.studio/api/v1/social`

**Authentication:** All endpoints require `Authorization: Bearer <your_api_key>`

---

## Follow operations

### Follow a user

<span className="badge badge--post">POST</span> `/api/v1/social/follow/{user_id}`

Follow another user. Their public content will appear in the follower's feed.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the user to follow |

#### Response `201 Created`

```json
{
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "follower_id": "550e8400-e29b-41d4-a716-446655440000",
  "followed_id": "650e8400-e29b-41d4-a716-446655440001",
  "created_at": "2026-04-25T14:00:00Z"
}
```

#### Errors

| Code | Reason |
|---|---|
| `400` | Already following, or cannot follow yourself |

#### Example

```bash
curl -X POST https://api.ainative.studio/api/v1/social/follow/650e8400-e29b-41d4-a716-446655440001 \
  -H "Authorization: Bearer $API_KEY"
```

```python
import requests

resp = requests.post(
    "https://api.ainative.studio/api/v1/social/follow/650e8400-e29b-41d4-a716-446655440001",
    headers={"Authorization": f"Bearer {api_key}"}
)
print(resp.json())
```

---

### Unfollow a user

<span className="badge badge--delete">DELETE</span> `/api/v1/social/follow/{user_id}`

Stop following a user.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the user to unfollow |

#### Response `200 OK`

```json
{
  "message": "Successfully unfollowed user",
  "user_id": "650e8400-e29b-41d4-a716-446655440001"
}
```

#### Errors

| Code | Reason |
|---|---|
| `404` | Not following this user |

---

## Friend request operations

### Send a friend request

<span className="badge badge--post">POST</span> `/api/v1/social/friend-request/{user_id}`

Send a bidirectional friend request to another user. The recipient must accept before a friendship is created.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the recipient |

#### Request body

```json
{
  "message": "Hey, let's connect!"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `message` | `string` | No | Optional personal message with the request |

#### Response `201 Created`

```json
{
  "id": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
  "requester_id": "550e8400-e29b-41d4-a716-446655440000",
  "recipient_id": "650e8400-e29b-41d4-a716-446655440001",
  "status": "pending",
  "message": "Hey, let's connect!",
  "created_at": "2026-04-25T14:01:00Z"
}
```

#### Errors

| Code | Reason |
|---|---|
| `400` | Already friends, request already pending, or cannot request yourself |

#### Example

```bash
curl -X POST https://api.ainative.studio/api/v1/social/friend-request/650e8400-e29b-41d4-a716-446655440001 \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"message": "Hey, lets connect!"}'
```

```python
resp = requests.post(
    "https://api.ainative.studio/api/v1/social/friend-request/650e8400-e29b-41d4-a716-446655440001",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"message": "Hey, lets connect!"}
)
```

---

### Accept a friend request

<span className="badge badge--post">POST</span> `/api/v1/social/friend-request/{request_id}/accept`

Accept a pending friend request. Creates a bidirectional friendship record.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `request_id` | `string` (UUID) | Yes | ID of the friend request to accept |

#### Response `200 OK`

```json
{
  "id": "9b2c3d4e-5f6a-7890-bcde-f01234567890",
  "user1_id": "550e8400-e29b-41d4-a716-446655440000",
  "user2_id": "650e8400-e29b-41d4-a716-446655440001",
  "created_at": "2026-04-25T14:05:00Z"
}
```

#### Errors

| Code | Reason |
|---|---|
| `400` | Request not in pending state, or you are not the recipient |

---

### Decline a friend request

<span className="badge badge--post">POST</span> `/api/v1/social/friend-request/{request_id}/decline`

Decline a pending friend request. The requester can send a new request later.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `request_id` | `string` (UUID) | Yes | ID of the friend request to decline |

#### Response `200 OK`

```json
{
  "id": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
  "requester_id": "550e8400-e29b-41d4-a716-446655440000",
  "recipient_id": "650e8400-e29b-41d4-a716-446655440001",
  "status": "declined",
  "message": "Hey, lets connect!",
  "created_at": "2026-04-25T14:01:00Z"
}
```

---

### Cancel a friend request

<span className="badge badge--delete">DELETE</span> `/api/v1/social/friend-request/{request_id}`

Cancel a friend request you sent (before it is accepted or declined).

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `request_id` | `string` (UUID) | Yes | ID of the friend request to cancel |

#### Response `200 OK`

```json
{
  "message": "Friend request canceled"
}
```

---

## Block operations

### Block a user

<span className="badge badge--post">POST</span> `/api/v1/social/block/{user_id}`

Block a user to prevent all interactions between you. Existing follow/friend relationships are severed.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the user to block |

#### Request body

```json
{
  "reason": "Spam"
}
```

| Field | Type | Required | Description |
|---|---|---|---|
| `reason` | `string` | No | Optional reason for blocking |

#### Response `201 Created`

```json
{
  "id": "aa1bb2cc-3dd4-5ee6-ff77-889900aabbcc",
  "blocker_id": "550e8400-e29b-41d4-a716-446655440000",
  "blocked_id": "650e8400-e29b-41d4-a716-446655440001",
  "reason": "Spam",
  "created_at": "2026-04-25T14:10:00Z"
}
```

#### Errors

| Code | Reason |
|---|---|
| `400` | User is already blocked, or cannot block yourself |

---

### Unblock a user

<span className="badge badge--delete">DELETE</span> `/api/v1/social/block/{user_id}`

Remove a block. The unblocked user can interact again.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the user to unblock |

#### Response `200 OK`

```json
{
  "message": "Successfully unblocked user",
  "user_id": "650e8400-e29b-41d4-a716-446655440001"
}
```

#### Errors

| Code | Reason |
|---|---|
| `404` | User is not blocked |

---

## Ignore operations

Ignoring a user hides their content from your feed without notifying them, unlike blocking which prevents all interaction.

### Ignore a user

<span className="badge badge--post">POST</span> `/api/v1/social/ignore/{user_id}`

Ignore a user to hide their content from your feed.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the user to ignore |

#### Response `201 Created`

```json
{
  "id": "bb2cc3dd-4ee5-6ff7-aa88-99bb00ccddee",
  "ignorer_id": "550e8400-e29b-41d4-a716-446655440000",
  "ignored_id": "650e8400-e29b-41d4-a716-446655440001",
  "created_at": "2026-04-25T14:12:00Z"
}
```

---

### Unignore a user

<span className="badge badge--delete">DELETE</span> `/api/v1/social/ignore/{user_id}`

Stop ignoring a user — their content will reappear in your feed.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | ID of the user to unignore |

#### Response `200 OK`

```json
{
  "message": "Successfully unignored user",
  "user_id": "650e8400-e29b-41d4-a716-446655440001"
}
```

#### Errors

| Code | Reason |
|---|---|
| `404` | User is not ignored |

---

## List operations

### Get followers

<span className="badge badge--get">GET</span> `/api/v1/social/{user_id}/followers`

Get the list of users following a given user.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | User whose followers to retrieve |

#### Query parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `offset` | `integer` | `0` | Number of items to skip |
| `limit` | `integer` | `20` | Items to return (1–100) |

#### Response `200 OK`

```json
{
  "followers": [
    {
      "id": "650e8400-e29b-41d4-a716-446655440001",
      "email": "alice@example.com",
      "full_name": "Alice Chen",
      "avatar_url": "https://cdn.ainative.studio/avatars/alice.jpg"
    }
  ],
  "total": 142,
  "offset": 0,
  "limit": 20
}
```

#### Example

```bash
curl "https://api.ainative.studio/api/v1/social/550e8400-e29b-41d4-a716-446655440000/followers?limit=20&offset=0" \
  -H "Authorization: Bearer $API_KEY"
```

```python
resp = requests.get(
    "https://api.ainative.studio/api/v1/social/550e8400-e29b-41d4-a716-446655440000/followers",
    headers={"Authorization": f"Bearer {api_key}"},
    params={"limit": 20, "offset": 0}
)
data = resp.json()
print(f"{data['total']} total followers")
```

---

### Get following

<span className="badge badge--get">GET</span> `/api/v1/social/{user_id}/following`

Get the list of users that a given user is following.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | User whose following list to retrieve |

#### Query parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `offset` | `integer` | `0` | Number of items to skip |
| `limit` | `integer` | `20` | Items to return (1–100) |

#### Response `200 OK`

```json
{
  "following": [
    {
      "id": "750e8400-e29b-41d4-a716-446655440002",
      "email": "bob@example.com",
      "full_name": "Bob Martinez",
      "avatar_url": null
    }
  ],
  "total": 55,
  "offset": 0,
  "limit": 20
}
```

---

### Get friends

<span className="badge badge--get">GET</span> `/api/v1/social/{user_id}/friends`

Get the list of confirmed (bidirectional) friends for a user.

#### Path parameters

| Parameter | Type | Required | Description |
|---|---|---|---|
| `user_id` | `string` (UUID) | Yes | User whose friend list to retrieve |

#### Query parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `offset` | `integer` | `0` | Number of items to skip |
| `limit` | `integer` | `20` | Items to return (1–100) |

#### Response `200 OK`

```json
{
  "friends": [
    {
      "id": "650e8400-e29b-41d4-a716-446655440001",
      "email": "alice@example.com",
      "full_name": "Alice Chen",
      "avatar_url": "https://cdn.ainative.studio/avatars/alice.jpg"
    }
  ],
  "total": 12,
  "offset": 0,
  "limit": 20
}
```

---

### Get pending friend requests

<span className="badge badge--get">GET</span> `/api/v1/social/me/friend-requests`

Get incoming friend requests pending your response.

#### Query parameters

| Parameter | Type | Default | Description |
|---|---|---|---|
| `offset` | `integer` | `0` | Number of items to skip |
| `limit` | `integer` | `20` | Items to return (1–100) |

#### Response `200 OK`

```json
{
  "requests": [
    {
      "id": "7a1b2c3d-4e5f-6789-abcd-ef0123456789",
      "sender_id": "750e8400-e29b-41d4-a716-446655440002",
      "receiver_id": "550e8400-e29b-41d4-a716-446655440000",
      "status": "pending",
      "message": "Hey, lets connect!",
      "created_at": "2026-04-25T14:01:00Z",
      "responded_at": null
    }
  ],
  "total": 3,
  "offset": 0,
  "limit": 20
}
```

---

### Get social stats

<span className="badge badge--get">GET</span> `/api/v1/social/me/stats`

Get aggregated social statistics for the authenticated user.

#### Response `200 OK`

```json
{
  "follower_count": 142,
  "following_count": 55,
  "friend_count": 12,
  "pending_requests_count": 3
}
```

#### Example

```bash
curl https://api.ainative.studio/api/v1/social/me/stats \
  -H "Authorization: Bearer $API_KEY"
```

```python
resp = requests.get(
    "https://api.ainative.studio/api/v1/social/me/stats",
    headers={"Authorization": f"Bearer {api_key}"}
)
stats = resp.json()
print(f"You have {stats['follower_count']} followers")
```

---

## Community search

<span className="badge badge--get">GET</span> `/api/v1/community/search/`

Search across users, posts, groups, and events in a single request.

#### Query parameters

| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
| `q` | `string` | — | Yes | Search query (2–200 characters) |
| `search_type` | `string` | `"all"` | No | `users`, `posts`, `groups`, `events`, or `all` |
| `tenant_id` | `string` (UUID) | — | No | Restrict results to a specific tenant |
| `offset` | `integer` | `0` | No | Pagination offset |
| `limit` | `integer` | `20` | No | Results per page (1–100) |

#### Response `200 OK`

```json
{
  "query": "machine learning",
  "search_type": "all",
  "users": {
    "items": [
      {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "username": "mlresearcher",
        "full_name": "Jane Doe",
        "bio": "ML engineer at AINative",
        "avatar_url": null
      }
    ],
    "total": 5,
    "offset": 0,
    "limit": 20
  },
  "posts": { "items": [], "total": 0, "offset": 0, "limit": 20 },
  "groups": { "items": [], "total": 0, "offset": 0, "limit": 20 },
  "events": {
    "items": [
      {
        "id": "abc12345-0000-0000-0000-000000000001",
        "title": "ML Workshop 2026",
        "description": "Hands-on machine learning workshop",
        "start_time": "2026-05-15T09:00:00Z",
        "location": "San Francisco"
      }
    ],
    "total": 1,
    "offset": 0,
    "limit": 20
  }
}
```

You can also search individual content types with dedicated endpoints:

| Endpoint | Description |
|---|---|
| `GET /api/v1/community/search/users?q=...` | Search users only |
| `GET /api/v1/community/search/posts?q=...` | Search posts only |
| `GET /api/v1/community/search/groups?q=...` | Search groups only |
| `GET /api/v1/community/search/events?q=...` | Search events only |

All dedicated endpoints accept the same `q`, `tenant_id`, `offset`, and `limit` parameters.

#### Search behavior

- Results respect tenant scoping — users see only content within their tenant unless `tenant_id` is overridden
- Blocked and ignored users are excluded from results
- Post body previews are truncated to 200 characters
- Minimum query length: 2 characters
