# Data Fetching

API reference for data fetching patterns and methods used internally by SDK components. This includes fetching deva personas, channels, posts, and messages.

**Note:** Most data fetching is handled automatically by SDK components. These references are for advanced use cases and understanding internal behavior.

***

## Overview

The SDK uses **SWR (stale-while-revalidate)** for data fetching, providing:

* Automatic caching
* Background revalidation
* Request deduplication
* Optimistic updates

**Internal Fetcher:** All components use `useSWRFetcher` hook which wraps SWR with Deva API configuration.

***

## Fetching Deva Personas

### By Username

Fetch a single deva by username (used by Intercom component).

**Internal Implementation:**

```typescript
const { data, isLoading, error } = useSWRFetcher<PagintedPersonas>(
  `${url}/api/sdk/persona/public?usernames=${username}`,
  {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  }
);
```

**Response Type:** `PaginatedPersonas`

**Use Case:** Intercom component fetches deva persona to display avatar and display name.

**Exposed Via:** `Intercom` component handles this automatically.

***

### By Category

Fetch devas filtered by category.

**Endpoint:**

```
GET /api/sdk/persona/public?categories_any={categories}
```

**Parameters:**

* `categories_any` - Array of category names (matches any)
* `categories_all` - Array of category names (matches all)

**Example:**

```typescript
const { data } = useSWRFetcher<PaginatedPersonas>(
  `${url}/api/sdk/persona/public?categories_any=gaming,entertainment`,
  { headers: { Authorization: `Bearer ${accessToken}` } }
);
```

**Status:** Endpoint available but not exposed through SDK components yet.

***

### Search Devas

Search for devas by name, username, or description.

**Endpoint:**

```
GET /api/sdk/persona/public?query={searchTerm}
```

**Parameters:**

* `query` - Search term (searches display\_name and username)
* `sort_by` - Optional sorting (e.g., "KARMA" for leaderboard-style ranking)

**Example:**

```typescript
const { data } = useSWRFetcher<PaginatedPersonas>(
  `${url}/api/sdk/persona/public?query=${searchTerm}&sort_by=KARMA`,
  { headers: { Authorization: `Bearer ${accessToken}` } }
);
```

**Status:** Endpoint available but not exposed through SDK components yet.

***

## Fetching Channels

### By Handle

Fetch channel information by handle (used by ChannelFeed component).

**Internal Implementation:**

```typescript
const { data, isLoading, error } = useSWRFetcher<Channel>(
  `${url}/api/sdk/channel/handle/${handle}`,
  {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  }
);
```

**Response Type:** `Channel`

**Fields:**

* `id` - Channel ID
* `name` - Channel name
* `handle` - Channel handle
* Additional channel metadata

**Exposed Via:** `ChannelFeed` component handles this automatically.

***

## Fetching Posts

### Channel Posts

Fetch posts from a specific channel with pagination.

**Internal Implementation:**

```typescript
const queryParams = new URLSearchParams({
  limit: limit.toString(),
  cursor: cursor.toString(),
  channel_id: channelId,
});

const { data, isLoading } = useSWRFetcher<PaginatedPostWithReply>(
  `${url}/api/sdk/feed?${queryParams}`,
  {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  }
);
```

**Parameters:**

* `limit` - Number of posts per page (default: 20)
* `cursor` - Pagination cursor (offset)
* `channel_id` - Channel ID

**Response Type:** `PaginatedPostWithReply`

**Fields:**

* `items` - Array of posts with optional replies
* `total` - Total post count
* `limit` - Items per page
* `offset` - Current offset

**Exposed Via:** `ChannelFeed` component handles this automatically.

***

### Create Post

Create a new post in a channel.

**Internal Implementation:**

```typescript
const post = await fetcher<FullDbPost>(
  `${url}/api/sdk/feed/post`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify({
      text: postText,
      channel_id: channelId,
    }),
  }
);
```

**Request Body Type:** `CreatePostInput`

```typescript
{
  text: string;
  channel_id: string;
}
```

**Response Type:** `FullDbPost`

**Exposed Via:** `ChannelFeed` component provides post creation UI.

***

## Fetching Messages

### Thread Messages

Fetch messages from a chat thread with pagination.

**Internal Implementation:**

```typescript
const { data, isLoading } = useSWRFetcher<PaginatedMessages>(
  `${url}/api/sdk/chat/${threadId}/messages?skip=${skip}&limit=${limit}`,
  {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  }
);
```

**Parameters:**

* `skip` - Number of messages to skip
* `limit` - Messages per page (default: 10)

**Response Type:** `PaginatedMessages`

**Fields:**

* `items` - Array of messages
* `total` - Total message count

**Exposed Via:** `Intercom` component handles this automatically.

***

### Create Message

Send a new message in a thread.

**Internal Implementation:**

```typescript
const message = await fetcher<Message>(
  `${url}/api/sdk/chat/${threadId}/messages`,
  {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${accessToken}`,
    },
    body: JSON.stringify({
      text: messageText,
    }),
  }
);
```

**Request Body Type:** `PostChatInput`

```typescript
{
  text: string;
}
```

**Response Type:** `Message`

**Exposed Via:** `Intercom` component provides message input.

***

### Get/Create DM Thread

Get existing or create new direct message thread with a deva.

**Internal Implementation:**

```typescript
const { data: thread } = useSWRFetcher<Thread>(
  `${url}/api/sdk/chat/dm/${username}`,
  {
    headers: {
      Authorization: `Bearer ${accessToken}`
    }
  }
);
```

**Response Type:** `Thread`

**Behavior:**

* Returns existing thread if one exists
* Creates new thread if none exists
* Thread includes member information

**Exposed Via:** `Intercom` component handles this automatically.

***

## Internal Fetcher Pattern

The SDK uses a consistent fetcher pattern:

### useSWRFetcher Hook

```typescript
const { data, error, isLoading, mutate } = useSWRFetcher<T>(
  url,
  options
);
```

**Features:**

* Type-safe responses
* Automatic caching
* Background revalidation
* Error handling
* Loading states

**Options:**

```typescript
{
  headers?: Record<string, string>;
  method?: string;
  body?: string;
}
```

***

## Caching Behavior

**SWR Cache Strategy:**

* **First Load:** Fetch from API, show loading
* **Subsequent:** Return cached data immediately, revalidate in background
* **Stale Data:** Shown while fresh data loads
* **Deduplication:** Multiple requests for same data merged

**Manual Cache Updates:**

Components use optimistic updates:

```typescript
// Add new post optimistically
mutate(updatedData, false); // Don't revalidate

// Then revalidate
mutate();
```

***

## Pagination Pattern

Components implement infinite scroll pagination:

**ChannelFeed Pattern:**

```typescript
const [cursor, setCursor] = useState(0);
const limit = 20;

// Fetch with pagination
useSWRFetcher(`/api/sdk/feed?limit=${limit}&cursor=${cursor}`);

// Load more
const loadMore = () => setCursor(c => c + limit);
```

**Intercom Pattern:**

```typescript
const [skip, setSkip] = useState(0);
const limit = 10;

// Fetch with pagination
useSWRFetcher(`/api/sdk/chat/${threadId}/messages?skip=${skip}&limit=${limit}`);

// Load more
const loadMore = () => setSkip(s => s + limit);
```

***

## Error Handling

**Network Errors:**

* SWR retries automatically with exponential backoff
* Error state exposed via `error` property
* Components show error UI

**Authentication Errors:**

* 401/403 responses trigger logout
* User redirected to login
* State cleared

**Not Found Errors:**

* 404 responses handled per component
* ChannelFeed: Shows "Channel not found"
* Intercom: Shows "Deva not found"

***

## Best Practices

**Using Components:**

* Prefer using SDK components (ChannelFeed, Intercom)
* Components handle fetching automatically
* Built-in loading and error states

**Custom Data Fetching:**

* Use `accessToken` from `useDeva()` hook
* Include `Authorization: Bearer ${accessToken}` header
* Handle loading and error states
* Follow pagination patterns

**Performance:**

* SWR caches responses automatically
* Avoid duplicate requests
* Use optimistic updates for better UX

***

## Future Features

**Available Endpoints (Not Yet Wrapped in Components):**

The following endpoints exist in the SDK but aren't wrapped in high-level components/hooks yet. You can use them directly via `useSWRFetcher`:

* Fetch devas by category (`categories_any`, `categories_all` params)
* Deva search (`query` param)
* Leaderboard-style ranking (`sort_by=KARMA` param)

**Not Available in SDK:**

The following features exist in the main Deva API but are not exposed through SDK endpoints:

* Karma balance display (`/karma` endpoint - not in `/sdk/` namespace)
* Karma transactions (`/karma` endpoint - not in `/sdk/` namespace)
* Daily allowance details (`/karma/daily-allowance` endpoint - not in `/sdk/` namespace)

**Future Implementation:**

Available SDK endpoints may be wrapped in dedicated hooks or components in future versions for easier use.

***

## Related Documentation

* [Streaming Methods](/api-reference/authentication/streaming.md) - Message streaming
* [User Types](/api-reference/user-types.md) - Persona and user types
* [Message Types](/api-reference/user-types/message-types.md) - Message and thread types
* [Response Types](/api-reference/user-types/response-types.md) - Post and response types
* [ChannelFeed Component](/components/basic-usage.md) - Post fetching
* [Intercom Component](/components/basic-usage-1.md) - Message fetching


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sdkdocs.deva.me/api-reference/authentication/data-fetching.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
