> For the complete documentation index, see [llms.txt](https://docs.holder.xyz/holder-api/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.holder.xyz/holder-api/contacts/get-contacts.md).

# Get Contacts

Our most robust API is our `contacts` query. It supports a wide variety of query capabilities for data around our contact model.

`GET /contacts`

#### Supported query params

| Query Param Name | Type   | Example               |
| ---------------- | ------ | --------------------- |
| limit            | number | 15 (default), max 100 |
| page             | number | 0 (default)           |
| sort             | Object | See below             |
| where            | Object | See below             |

#### Sort Types & Examples

The types for our `sort` parameter is as follows:

```typescript
enum SortDirection {
  ASC,
  DESC,
}

interface ContactSortInput
  extends Record<string, SortDirection | undefined> {
  numberOfNFTs?: SortDirection;
  balance?: SortDirection;
  createdAt?: SortDirection;
  email?: SortDirection;
  twitterHandle?: SortDirection;
  discordUsername?: SortDirection;
}
```

We currently only support passing in a single sort value. If you pass in multiple, your results may vary or be inconsistent. A good example (and the default for the table in our UI) can be found below:

```javascript
{ createdAt: 'DESC' }
```

#### Where Types & Examples

The types for our `where` clause parameter is as follows:

```typescript
interface TimestampRange {
  start: number;
  end: number;
}

interface NumberOfContractNFTs {
  contractAddress: string;
  numberOfHolds: number;
}

interface Trait {
  id: string;
  value: string | Array<string>;
}

interface CustomField {
  fieldId: string;
  value: string | boolean;
}

interface ContactWhereInput {
  // Contact filters
  id_eq?: string;
  id_in?: Array<string>;

  email_eq?: string;
  email_neq?: string;
  email_isNull?: boolean;
  email_isNotNull?: boolean;

  phoneNumber_eq?: string;
  phoneNumber_neq?: string;
  phoneNumber_isNull?: boolean;
  phoneNumber_isNotNull?: boolean;

  discordUsername_eq?: string;
  discordUsername_neq?: string;
  discordUsername_isNull?: boolean;
  discordUsername_isNotNull?: boolean;

  twitterHandle_eq?: string;
  twitterHandle_neq?: string;
  twitterHandle_isNull?: boolean;
  twitterHandle_isNotNull?: boolean;

  createdAt_eq?: number;
  createdAt_neq?: number;
  createdAt_gt?: number;
  createdAt_gte?: number;
  createdAt_lt?: number;
  createdAt_lte?: number;
  createdAt_between?: TimestampRange;

  filledForm_eq?: string;
  filledForm_neq?: string;

  tag_eq?: string;
  tag_neq?: string;

  smsSent_eq?: string;
  smsSent_neq?: string;

  smsOptOut_eq?: boolean;
  smsOptOut_neq?: boolean;

  // List filters
  listId_eq?: string;
  listId_neq?: string;

  // Contact custom field filters
  customField_eq?: CustomField;
  customField_neq?: CustomField;
  customField_isNull?: CustomField;
  customField_isNotNull?: CustomField;

  // Wallet filters
  walletAddress_eq?: string;
  walletAddress_neq?: string;
  walletAddress_in?: Array<string>;

  balance_eq?: number;
  balance_neq?: number;
  balance_gt?: number;
  balance_gte?: number;
  balance_lt?: number;
  balance_lte?: number;

  xmtpEnabled_eq?: boolean;
  xmtpEnabled_neq?: boolean;
  xmtpEnabled_isNull?: boolean;
  xmtpEnabled_isNotNull?: boolean;

  // NFT filters
  contractAddress_eq?: string;
  contractAddress_neq?: string;

  tokenId_in?: Array<string>;

  amount_eq?: number;
  amount_neq?: number;
  amount_gt?: number;
  amount_gte?: number;
  amount_lt?: number;
  amount_lte?: number;

  trait_eq?: Trait;
  trait_neq?: Trait;
  trait_in?: Trait;
  trait_nin?: Trait;

  purchasedDate_eq?: number;
  purchasedDate_neq?: number;
  purchasedDate_gt?: number;
  purchasedDate_gte?: number;
  purchasedDate_lt?: number;
  purchasedDate_lte?: number;
  purchasedDate_between?: TimestampRange;

  numberOfNFTs_eq?: number;
  numberOfNFTs_neq?: number;
  numberOfNFTs_gt?: number;
  numberOfNFTs_gte?: number;
  numberOfNFTs_lt?: number;
  numberOfNFTs_lte?: number;

  // Discord filters
  discordJoinDate_eq?: number;
  discordJoinDate_neq?: number;
  discordJoinDate_gt?: number;
  discordJoinDate_gte?: number;
  discordJoinDate_lt?: number;
  discordJoinDate_lte?: number;
  discordJoinDate_between?: TimestampRange;

  discordJoinDateGuild_eq?: number;
  discordJoinDateGuild_neq?: number;
  discordJoinDateGuild_gt?: number;
  discordJoinDateGuild_gte?: number;
  discordJoinDateGuild_lt?: number;
  discordJoinDateGuild_lte?: number;
  discordJoinDateGuild_between?: TimestampRange;

  discordActivity_eq?: number;
  discordActivity_neq?: number;
  discordActivity_gt?: number;
  discordActivity_gte?: number;
  discordActivity_lt?: number;
  discordActivity_lte?: number;
  discordActivity_between?: TimestampRange;

  discordMsgNum_eq?: number;
  discordMsgNum_neq?: number;
  discordMsgNum_gt?: number;
  discordMsgNum_gte?: number;
  discordMsgNum_lt?: number;
  discordMsgNum_lte?: number;

  discordRole_eq?: string;
  discordRole_neq?: string;

  // Recursive filters
  AND?: Array<ContactWhereInput>;
  OR?: Array<ContactWhereInput>;
  NOT?: Array<ContactWhereInput>;

  // Special operators for compound NFT filters
  AND_nft?: Array<ContactWhereInput>;
  OR_nft?: Array<ContactWhereInput>;
  NOT_nft?: Array<ContactWhereInput>;

  // Special operators for compound NFT filter by numberOfHolds
  numberOfContractNFTs_eq?: NumberOfContractNFTs;
  numberOfContractNFTs_neq?: NumberOfContractNFTs;
  numberOfContractNFTs_gt?: NumberOfContractNFTs;
  numberOfContractNFTs_gte?: NumberOfContractNFTs;
  numberOfContractNFTs_lt?: NumberOfContractNFTs;
  numberOfContractNFTs_lte?: NumberOfContractNFTs;
}
```

This list is evolving, and some might even be missing, but the pattern should be fairly clear for our queries moving forward. Note that it is a recursive structure, but deeply nesting filters will slow down the query. We do not make any specific performance guarantees. Here are a few examples:

```javascript
// Finds all contacts in your account that have a wallet balance greater than 1 ETH
// and have XMTP (wallet messaging) enabled.
{
  where: {
    AND: [
      {
        balance_gt: 1
      },
      {
        xmtpEnabled_eq: true
      }
    ]
  }
}

// NFT filters are a special case for our recursive AND/OR/NOT stucture. This
// will find all contacts in your account that own a Gold BoredApeYachtClub or
// a Cosmic Moonbirds.
{
  where: {
    OR: [
      {
        AND_nft: [
          {
            contractAddress_eq: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
          },
          {
            trait_eq: {
              id: "<our internal id for Fur from traits query>",
              value: "Solid Gold"
            }
          },
          {
            amount_gt: 0
          }
        ]
      },
      {
        AND_nft: [
          {
            contractAddress_eq: "0x23581767a106ae21c074b2276d25e5c3e136a68b"
          },
          {
            trait_eq: {
              id: "<our internal id for Body from traits query>",
              value: "Cosmic"
            }
          },
          {
            amount_gt: 0
          }
        ]
      }
    ]
  }
}
```

#### Need Help?

This is a complex query, so it is hard to account for every edge case in our documentation. If you find yourself trying to figure something out but it just isn't working, please reach out and let us know!


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.holder.xyz/holder-api/contacts/get-contacts.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
