> ## Documentation Index
> Fetch the complete documentation index at: https://docs.inboxapp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Team setup

> Managing team members and roles in Inbox

## Overview

Teams in Inbox organize your account links, prospects, and conversations. This guide covers retrieving team information and managing team members via the API.

## Get team information

Retrieve your team details:

<CodeGroup>
  ```typescript team.ts theme={null}
  const { data: team } = await client.get("/team");

  console.log("Team:", team.name);
  console.log("Currency:", team.currency);
  console.log("Created:", team.createdAt);
  ```

  ```bash cURL theme={null}
  curl https://inboxapp.com/api/v1/team \
    -H "Authorization: Bearer $INBOX_API_TOKEN"
  ```
</CodeGroup>

**Response:**

```json theme={null}
{
  "id": "hzcai5t59nn9vsck3rbuepyg",
  "name": "Acme Corp",
  "slug": "acme-corp",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": null,
  "currency": "USD",
  "allowSupportAccess": false
}
```

| Field                | Description                                              |
| -------------------- | -------------------------------------------------------- |
| `id`                 | Inbox team ID                                            |
| `name`               | Team display name                                        |
| `slug`               | URL-friendly team identifier                             |
| `currency`           | Currency used for prospect valuations (e.g., `"USD"`)    |
| `allowSupportAccess` | Whether the Inbox support team can access your workspace |

## List team members

Get all members of your team:

<CodeGroup>
  ```typescript members.ts theme={null}
  const { data: members } = await client.get("/members");

  console.log(`Team has ${members.length} members`);
  members.forEach((member) => {
    console.log(`${member.name} (${member.email}) - ${member.role}`);
  });
  ```

  ```bash cURL theme={null}
  curl https://inboxapp.com/api/v1/members \
    -H "Authorization: Bearer $INBOX_API_TOKEN"
  ```
</CodeGroup>

**Response:**

```json theme={null}
[
  {
    "id": "r3km7xj9wq5p2bvnhfdteoly",
    "userId": "usr4hn8xj2wq5p1bvnhfdteo",
    "name": "Jane Smith",
    "email": "jane@acmecorp.com",
    "image": "https://lh3.googleusercontent.com/...",
    "role": "owner",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": null
  },
  {
    "id": "s4ln8yk0xr6q3cw1behsifup",
    "userId": "usr5io9yk3xr6q2cw1behsifu",
    "name": "John Doe",
    "email": "john@acmecorp.com",
    "image": "https://lh3.googleusercontent.com/...",
    "role": "admin",
    "createdAt": "2024-02-01T09:00:00.000Z",
    "updatedAt": null
  },
  {
    "id": "t5mo9zl1ys7r4dx2cfitjgvqw",
    "userId": "usr6jp0zl4ys7r3dx2cfitjgv",
    "name": "Alice Johnson",
    "email": "alice@acmecorp.com",
    "image": null,
    "role": "user",
    "createdAt": "2024-02-15T14:00:00.000Z",
    "updatedAt": null
  }
]
```

<Note>
  `GET /members` returns a flat array, not a wrapped object. The same applies to
  `GET /account-links`, `GET /tags`, and `GET /statuses`.
</Note>

## Get specific member

Retrieve details for a specific member:

```typescript theme={null}
const { data: member } = await client.get(`/members/${memberId}`);
console.log("Member:", member.name);
```

## Member roles

| Role    | Permissions                                    |
| ------- | ---------------------------------------------- |
| `owner` | Full access, billing management, team deletion |
| `admin` | Full access except billing and team deletion   |
| `user`  | Access to assigned threads and features        |

## Thread assignment

Assign threads to team members for workload distribution:

```typescript theme={null}
// Assign a thread to a member
await client.patch(`/threads/${threadId}`, {
  assigneeId: "r3km7xj9wq5p2bvnhfdteoly",
});

// Unassign a thread
await client.patch(`/threads/${threadId}`, {
  assigneeId: null,
});
```

## Filter by assignee

Get threads assigned to specific members:

```typescript theme={null}
// Get threads assigned to a specific member
const { data } = await client.get("/threads", {
  params: {
    "filters[assignees][selectedIds][0]": "r3km7xj9wq5p2bvnhfdteoly",
  },
});

// Get unassigned threads
const { data: unassigned } = await client.get("/threads", {
  params: {
    "filters[assignees][noAssignee]": true,
  },
});
```

## Common patterns

### Round-robin assignment

Distribute new threads evenly across team members:

```typescript theme={null}
async function getTeamMembers(): Promise<string[]> {
  const { data: members } = await client.get("/members");
  return members.filter((m: any) => m.role !== "owner").map((m: any) => m.id);
}

class RoundRobinAssigner {
  private members: string[] = [];
  private currentIndex = 0;

  async initialize() {
    this.members = await getTeamMembers();
  }

  next(): string {
    const memberId = this.members[this.currentIndex];
    this.currentIndex = (this.currentIndex + 1) % this.members.length;
    return memberId;
  }
}

// Usage
const assigner = new RoundRobinAssigner();
await assigner.initialize();

async function assignNewThread(threadId: string) {
  const memberId = assigner.next();
  await client.patch(`/threads/${threadId}`, {
    assigneeId: memberId,
  });
  console.log(`Assigned thread to ${memberId}`);
}
```

### Workload-based assignment

Assign to the team member with the fewest open threads. Since the API doesn't return a total count, you need to paginate to get real numbers:

```typescript theme={null}
async function countThreadsForMember(memberId: string): Promise<number> {
  let count = 0;
  let cursorId: string | undefined;
  let cursorTimestamp: string | undefined;

  do {
    const { data } = await client.get("/threads", {
      params: {
        "filters[assignees][selectedIds][0]": memberId,
        inbox: "default",
        limit: 100,
        ...(cursorId && { cursorId, cursorTimestamp }),
      },
    });

    count += data.threads.length;
    cursorId = data.nextCursor?.id;
    cursorTimestamp = data.nextCursor?.timestamp;
  } while (cursorId);

  return count;
}

async function assignToLeastBusy(threadId: string) {
  const { data: members } = await client.get("/members");

  let minMember = "";
  let minCount = Infinity;

  for (const member of members) {
    if (member.role === "owner") continue;

    const count = await countThreadsForMember(member.id);
    if (count < minCount) {
      minCount = count;
      minMember = member.id;
    }
  }

  if (minMember) {
    await client.patch(`/threads/${threadId}`, {
      assigneeId: minMember,
    });
    console.log(`Assigned to ${minMember} (${minCount} open threads)`);
  }
}
```

<Note>
  This makes multiple API calls per member. For teams with many members or
  threads, consider caching workload counts and refreshing periodically rather
  than computing on every assignment.
</Note>

### Role-based routing

Route threads based on message content to appropriate team members:

```typescript theme={null}
interface RoutingConfig {
  memberId: string;
  keywords: string[];
}

const routingRules: RoutingConfig[] = [
  {
    memberId: "s4ln8yk0xr6q3cw1behsifup",
    keywords: ["pricing", "demo", "quote", "buy", "purchase"],
  },
  {
    memberId: "t5mo9zl1ys7r4dx2cfitjgvqw",
    keywords: ["help", "issue", "problem", "bug", "error", "not working"],
  },
];

async function routeByContent(threadId: string, messageText: string) {
  const text = messageText.toLowerCase();

  for (const rule of routingRules) {
    if (rule.keywords.some((k) => text.includes(k))) {
      await client.patch(`/threads/${threadId}`, {
        assigneeId: rule.memberId,
      });
      console.log(`Routed to ${rule.memberId} based on keywords`);
      return rule.memberId;
    }
  }

  return null;
}
```

## Best practices

<AccordionGroup>
  <Accordion title="Keep assignment balanced" icon="scale">
    Use workload-based or round-robin assignment to prevent bottlenecks.
  </Accordion>

  <Accordion title="Set clear ownership" icon="user-check">
    Each thread should have a clear owner. Avoid leaving threads unassigned for
    too long.
  </Accordion>
</AccordionGroup>

## Related endpoints

<CardGroup cols={2}>
  <Card title="Get team" icon="building" href="/api-reference/teams/get-team">
    GET /team
  </Card>

  <Card title="List members" icon="users" href="/api-reference/members/list-members">
    GET /members
  </Card>

  <Card title="Get member" icon="user" href="/api-reference/members/get-member">
    GET /members/{id}
  </Card>

  <Card title="Update thread" icon="pencil" href="/api-reference/threads/update-thread">
    PATCH /threads/{id}
  </Card>
</CardGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Account links" icon="link" href="/configuration/account-links">
    Connect X accounts
  </Card>

  <Card title="Managing threads" icon="messages-square" href="/guides/managing-threads">
    Thread operations and filtering
  </Card>

  <Card title="Working with prospects" icon="user" href="/guides/prospects">
    Manage prospect data
  </Card>

  <Card title="Tags & statuses" icon="tags" href="/guides/tags-and-statuses">
    Organize prospects
  </Card>
</CardGroup>
