Skip to main content

Overview

The Inbox API uses bracket notation for encoding complex data types (objects and arrays) in query parameters. This guide covers the encoding rules and common patterns.

Objects

Objects are encoded using bracket notation with property names. Object value:
{
  "id": "l44e15irdq4db30i77cgphhx",
  "timestamp": "2025-01-15T10:30:00.000Z"
}
Encoded in URL:
?cursorId=l44e15irdq4db30i77cgphhx&cursorTimestamp=2025-01-15T10:30:00.000Z

Cursor example

// Preferred: flat cursor parameters
const { data } = await client.get('/threads', {
  params: {
    cursorId: 'l44e15irdq4db30i77cgphhx',
    cursorTimestamp: '2025-01-15T10:30:00.000Z',
    limit: 50
  }
});
Use the flat cursorId and cursorTimestamp parameters for pagination. The bracket notation form (cursor[id], cursor[timestamp]) is also supported but deprecated.

Arrays

Arrays can be encoded in three ways. All are supported by the API. Array value:
["df6jbw4h36qm5d9iu2sgn7kx", "g7ht2kw9xr5m8fp3yjnbqvce"]

Option 1: repeated parameters (simplest)

?accountLinkIds=df6jbw4h36qm5d9iu2sgn7kx&accountLinkIds=g7ht2kw9xr5m8fp3yjnbqvce

Option 2: empty bracket notation

Explicitly denotes an array. Useful when there’s only one value:
?accountLinkIds[]=df6jbw4h36qm5d9iu2sgn7kx&accountLinkIds[]=g7ht2kw9xr5m8fp3yjnbqvce

Option 3: indexed bracket notation

Most explicit. Allows reordering and sparse arrays:
?accountLinkIds[0]=df6jbw4h36qm5d9iu2sgn7kx&accountLinkIds[1]=g7ht2kw9xr5m8fp3yjnbqvce

Thread filters

The GET /threads endpoint supports advanced filtering via the filters parameter using nested bracket notation.

By tags

// Threads with ANY of these tags (OR logic)
const { data } = await client.get('/threads', {
  params: {
    'filters[tags][selectedIds][0]': 't8rvk2m5j0xn4wq7ybftcael',
    'filters[tags][selectedIds][1]': 'u9swl3n6k1yo5xr8zcgudbfm'
  }
});

// Threads with NO tags
const { data: untagged } = await client.get('/threads', {
  params: {
    'filters[tags][noTags]': true
  }
});

By status

// Threads with prospects in specific statuses
const { data } = await client.get('/threads', {
  params: {
    'filters[statuses][selectedIds][0]': 's3km7xj9wq5p2bvnhfdteoly',
    'filters[statuses][selectedIds][1]': 's4ln8yk0xr6q3cw1behsifup'
  }
});

// Threads with no status set
const { data: noStatus } = await client.get('/threads', {
  params: {
    'filters[statuses][noStatus]': true
  }
});

By assignee

// Threads assigned to specific members
const { data } = await client.get('/threads', {
  params: {
    'filters[assignees][selectedIds][0]': 'r3km7xj9wq5p2bvnhfdteoly'
  }
});

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

By campaign

// Threads from specific campaigns
const { data } = await client.get('/threads', {
  params: {
    'filters[campaigns][selectedIds][0]': 'c5nwp8r2j3ym6at0xbkqhfvg'
  }
});

// Threads not from any campaign
const { data: noCampaign } = await client.get('/threads', {
  params: {
    'filters[campaigns][noCampaign]': true
  }
});

Sort order

const { data } = await client.get('/threads', {
  params: {
    'filters[sortOrder]': 'desc' // or 'asc'
  }
});

Combined filters

Multiple filters combine with AND logic:
// Active threads + qualified status + assigned to specific member
const { data } = await client.get('/threads', {
  params: {
    inbox: 'default',
    'accountLinkIds[0]': 'df6jbw4h36qm5d9iu2sgn7kx',
    'filters[statuses][selectedIds][0]': 's3km7xj9wq5p2bvnhfdteoly',
    'filters[assignees][selectedIds][0]': 'r3km7xj9wq5p2bvnhfdteoly',
    limit: 50
  }
});

Filter parameter reference

FilterParameterDescription
Tags (include)filters[tags][selectedIds][N]Show threads with any of these tag IDs
Tags (exclude)filters[tags][noTags]Show only untagged threads
Statuses (include)filters[statuses][selectedIds][N]Show threads with any of these status IDs
Statuses (exclude)filters[statuses][noStatus]Show only threads with no status
Assignees (include)filters[assignees][selectedIds][N]Show threads assigned to these member IDs
Assignees (exclude)filters[assignees][noAssignee]Show only unassigned threads
Campaigns (include)filters[campaigns][selectedIds][N]Show threads from these campaigns
Campaigns (exclude)filters[campaigns][noCampaign]Show only non-campaign threads
Sort orderfilters[sortOrder]"desc" (newest first, default) or "asc" (oldest first)
Inbox viewinbox"default", "no-reply", "requests", or "archived"
Account linksaccountLinkIds[N]Filter by specific account link IDs
Page sizelimit1100 (default 20)

URL encoding special characters

Values containing special characters must be URL-encoded:
CharacterEncoded
Space%20 or +
+%2B
&%26
=%3D
[%5B
]%5D
:%3A
Most HTTP clients handle this automatically.

Helper function

A utility for encoding filter parameters:
function buildFilterParams(filters: {
  tagIds?: string[];
  statusIds?: string[];
  assigneeIds?: string[];
  campaignIds?: string[];
  noTags?: boolean;
  noStatus?: boolean;
  noAssignee?: boolean;
  noCampaign?: boolean;
  sortOrder?: 'asc' | 'desc';
}): Record<string, string | boolean> {
  const params: Record<string, string | boolean> = {};

  filters.tagIds?.forEach((id, i) => {
    params[`filters[tags][selectedIds][${i}]`] = id;
  });
  filters.statusIds?.forEach((id, i) => {
    params[`filters[statuses][selectedIds][${i}]`] = id;
  });
  filters.assigneeIds?.forEach((id, i) => {
    params[`filters[assignees][selectedIds][${i}]`] = id;
  });
  filters.campaignIds?.forEach((id, i) => {
    params[`filters[campaigns][selectedIds][${i}]`] = id;
  });

  if (filters.noTags) params['filters[tags][noTags]'] = true;
  if (filters.noStatus) params['filters[statuses][noStatus]'] = true;
  if (filters.noAssignee) params['filters[assignees][noAssignee]'] = true;
  if (filters.noCampaign) params['filters[campaigns][noCampaign]'] = true;
  if (filters.sortOrder) params['filters[sortOrder]'] = filters.sortOrder;

  return params;
}

// Usage
const { data } = await client.get('/threads', {
  params: {
    inbox: 'default',
    ...buildFilterParams({
      tagIds: ['t8rvk2m5j0xn4wq7ybftcael'],
      noAssignee: true
    }),
    limit: 50
  }
});

Common mistakes

Wrong: Using incorrect filter key structure
// These parameter names are WRONG
const { data } = await client.get('/threads', {
  params: {
    'filter[tagIds][0]': 'tag_abc',           // Wrong key
    'filter[assignedToMemberIds][0]': 'member_abc', // Wrong key
    'filter[noAssignee]': true,               // Wrong key
    inboxView: 'default',                     // Wrong param name
    accountLinkId: 'acc_abc',                 // Wrong param name
  }
});
Correct:
const { data } = await client.get('/threads', {
  params: {
    'filters[tags][selectedIds][0]': 't8rvk2m5j0xn4wq7ybftcael',
    'filters[assignees][selectedIds][0]': 'r3km7xj9wq5p2bvnhfdteoly',
    'filters[assignees][noAssignee]': true,
    inbox: 'default',
    'accountLinkIds[0]': 'df6jbw4h36qm5d9iu2sgn7kx',
  }
});