Get profiles

📘

full code repo https://github.com/lens-protocol/lens-api-examples

The profile query has a few different ways you can query the profiles. Using the power of GraphQL is super flexible and allows the same endpoint to be used in many different cases.

API details

Below is the overview of the entire interface but we dig into specific queries below.

📘

Hot tip

If you do not know GraphQL that well remember things can be nullable if defined. In the schema how GraphQL knows it's nullable is without the ! at the end here is an example:

Not nullable:

ownedBy: EthereumAddress!

Nullable:

ownedBy: EthereumAddress

It's always worth generating the TypeScript types for the schema if your application is TypeScript here is a reference to how you would do that - https://www.apollographql.com/blog/tooling/apollo-codegen/typescript-graphql-code-generator-generate-graphql-types/

{
  "data": {
    "profiles": {
      "items": [
        {
          "id": "0x01",
          "name": "Josh",
          "bio": "Amazing docs",
          "attributes": [
            {
              "displayType": null,
              "traitType": null,
              "key": "custom_field",
              "value": "yes this is custom"
            }
          ],
          "followNftAddress": null,
          "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP",
          "isDefault": false,
          "picture": null,
          "handle": "josh.dev",
          "coverPicture": null,
          "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82",
          "dispatcher": {
            "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF"
          },
          "stats": {
            "totalFollowers": 2,
            "totalFollowing": 1,
            "totalPosts": 1,
            "totalComments": 0,
            "totalMirrors": 0,
            "totalPublications": 1,
            "totalCollects": 6
          },
          "followModule": null
        }
      ],
      "pageInfo": {
        "prev": "{\"offset\":0}",
        "next": "{\"offset\":1}",
        "totalCount": 1
      }
    }
  }
}
type Query { 
  profiles(request: ProfileQueryRequest!): PaginatedProfileResult!
}
input ProfileQueryRequest {
  limit: Int
  cursor: Cursor

  # The profile ids
  profileIds: [ProfileId!]

  # The ethereum addresses
  ownedBy: [EthereumAddress!]

  # The handles for the profile
  handles: [Handle!]

  # The mirrored publication id
  whoMirroredPublicationId: InternalPublicationId
}

You will see the paging result behavior repeated a lot in the API; this is to allow you to fetch a certain amount and then page it for the most optimal request speed. Every time something is wrapped in a paging result you will always get returned a pageInfo which holds the cursors for the previous and next alongside the total count which exists in the database. These cursors are just pointers for the server to get to the next result and do not need to be understood by your client or server. If you ever want to then page to the next result you can pass these previous and next cursor in the request cursor property.

Now you see the base query let's look at how we can use different request parameters to request profiles.

Get by profile ids

You can get the profiles by passing in an array of profileIds please note if you try to pass in the ownedBy or handles or whoMirroredPublicationIdalongside this you will get aValidationError` thrown. The same will happen if you pass in an empty array.

query Profiles {
  profiles(request: { profileIds: ["0x01"], limit: 10 }) {
    items {
      id
      name
      bio
      attributes {
        displayType
        traitType
        key
        value
      }
      followNftAddress
      metadata
      isDefault
      picture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      handle
      coverPicture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      ownedBy
      dispatcher {
        address
        canUseRelay
      }
      stats {
        totalFollowers
        totalFollowing
        totalPosts
        totalComments
        totalMirrors
        totalPublications
        totalCollects
      }
      followModule {
        ... on FeeFollowModuleSettings {
          type
          amount {
            asset {
              symbol
              name
              decimals
              address
            }
            value
          }
          recipient
        }
        ... on ProfileFollowModuleSettings {
         type
        }
        ... on RevertFollowModuleSettings {
         type
        }
      }
    }
    pageInfo {
      prev
      next
      totalCount
    }
  }
}
{
  "data": {
    "profiles": {
      "items": [
        {
          "id": "0x01",
          "name": "Josh",
          "bio": "Amazing docs",
          "attributes": [
            {
              "displayType": null,
              "traitType": null,
              "key": "custom_field",
              "value": "yes this is custom"
            }
          ],
          "followNftAddress": null,
          "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP",
          "isDefault": false,
          "picture": null,
          "handle": "josh.dev",
          "coverPicture": null,
          "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82",
          "dispatcher": {
            "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF"
          },
          "stats": {
            "totalFollowers": 2,
            "totalFollowing": 1,
            "totalPosts": 1,
            "totalComments": 0,
            "totalMirrors": 0,
            "totalPublications": 1,
            "totalCollects": 6
          },
          "followModule": null
        }
      ],
      "pageInfo": {
        "prev": "{\"offset\":0}",
        "next": "{\"offset\":1}",
        "totalCount": 1
      }
    }
  }
}

Get by owned by

You can get the profiles by passing in an array of ownedBy which is an array of ethereum addresses, please note if you try to pass in the profileIds or handles or whoMirroredPublicationIdalongside this you will get aValidationError` thrown. The same will happen if you pass in an empty array.

query Profiles {
  profiles(request: { ownedBy: ["0xD020E01C0c90Ab005A01482d34B808874345FD82"], limit: 10 }) {
    items {
      id
      name
      bio
      attributes {
        displayType
        traitType
        key
        value
      }
      followNftAddress
      metadata
      isDefault
      picture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      handle
      coverPicture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      ownedBy
      dispatcher {
        address
        canUseRelay
      }
      stats {
        totalFollowers
        totalFollowing
        totalPosts
        totalComments
        totalMirrors
        totalPublications
        totalCollects
      }
      followModule {
        ... on FeeFollowModuleSettings {
          type
          amount {
            asset {
              symbol
              name
              decimals
              address
            }
            value
          }
          recipient
        }
        ... on ProfileFollowModuleSettings {
         type
        }
        ... on RevertFollowModuleSettings {
         type
        }
      }
    }
    pageInfo {
      prev
      next
      totalCount
    }
  }
}
{
  "data": {
    "profiles": {
      "items": [
        {
          "id": "0x01",
          "name": "Josh",
          "bio": "Amazing docs",
          "attributes": [
            {
              "displayType": null,
              "traitType": null,
              "key": "custom_field",
              "value": "yes this is custom"
            }
                    ],
          "followNftAddress": null,
                    "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP",
                    "isDefault": false,
          "picture": null,
          "handle": "josh.test",
          "coverPicture": null,
          "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82",
          "dispatcher": {
            "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF"
          },
          "stats": {
            "totalFollowers": 2,
            "totalFollowing": 1,
            "totalPosts": 1,
            "totalComments": 0,
            "totalMirrors": 0,
            "totalPublications": 1,
            "totalCollects": 6
          },
          "followModule": null
        }
      ],
      "pageInfo": {
        "prev": "{\"offset\":0}",
        "next": "{\"offset\":1}",
        "totalCount": 1
      }
    }
  }
}

Get by handles

You can get the profiles by passing in an array of handles, please note if you try to pass in the profileIds or ownedByor whoMirroredPublicationIdalongside this you will get aValidationError` thrown. The same will happen if you pass in an empty array.

query Profiles {
  profiles(request: { handles: ["josh.test"], limit: 1 }) {
    items {
      id
      name
      bio
      attributes {
        displayType
        traitType
        key
        value
      }
      followNftAddress
      metadata
      isDefault
      picture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      handle
      coverPicture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      ownedBy
      dispatcher {
        address
        canUseRelay
      }
      stats {
        totalFollowers
        totalFollowing
        totalPosts
        totalComments
        totalMirrors
        totalPublications
        totalCollects
      }
      followModule {
        ... on FeeFollowModuleSettings {
          type
          amount {
            asset {
              symbol
              name
              decimals
              address
            }
            value
          }
          recipient
        }
        ... on ProfileFollowModuleSettings {
         type
        }
        ... on RevertFollowModuleSettings {
         type
        }
      }
    }
    pageInfo {
      prev
      next
      totalCount
    }
  }
}
{
  "data": {
    "profiles": {
      "items": [
        {
          "id": "0x01",
          "name": "Josh",
          "bio": "Amazing docs",
          "attributes": [
            {
              "displayType": null,
              "traitType": null,
              "key": "custom_field",
              "value": "yes this is custom"
            }
          ],
          "followNftAddress": null,
          "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP",
          "isDefault": false,
          "picture": null,
          "handle": "josh.test",
          "coverPicture": null,
          "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82",
          "dispatcher": {
            "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF"
          },
          "stats": {
            "totalFollowers": 2,
            "totalFollowing": 1,
            "totalPosts": 1,
            "totalComments": 0,
            "totalMirrors": 0,
            "totalPublications": 1,
            "totalCollects": 6
          },
          "followModule": null
        }
      ],
      "pageInfo": {
        "prev": "{\"offset\":0}",
        "next": "{\"offset\":1}",
        "totalCount": 1
      }
    }
  }
}

Get by who has mirrored a publication

You can get the profiles of who mirrored a publication using the whoMirroredPublicationId, please note if you try to pass in the profileIds or ownedBy or handlesalongside this you will get aValidationError` thrown.

📘

Did you know...

The publication id is not unique in the smart contract its a counter per each profile. So if @josh posts a publication that will be publication 1 for his profile and then if @josh2 posts a publication that will be publication 1 for his profile. The backend generates what we call an InternalPublicationId which is built up from {profileId}-{publicationId} creating a unique ID that can be queried against our database. You will see that InternalPublicationId is used on all responses and also used in any request you which to do.

query Profiles {
  profiles(request: { whoMirroredPublicationId: "0x09-0x01", limit: 10 }) {
    items {
      id
      name
      bio
      attributes {
        displayType
        traitType
        key
        value
      }
      followNftAddress
      metadata
      isDefault
      picture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      handle
      coverPicture {
        ... on NftImage {
          contractAddress
          tokenId
          uri
          verified
        }
        ... on MediaSet {
          original {
            url
            mimeType
          }
        }
        __typename
      }
      ownedBy
      dispatcher {
        address
        canUseRelay
      }
      stats {
        totalFollowers
        totalFollowing
        totalPosts
        totalComments
        totalMirrors
        totalPublications
        totalCollects
      }
      followModule {
        ... on FeeFollowModuleSettings {
          type
          amount {
            asset {
              symbol
              name
              decimals
              address
            }
            value
          }
          recipient
        }
        __typename
      }
    }
    pageInfo {
      prev
      next
      totalCount
    }
  }
}
{
  "data": {
    "profiles": {
      "items": [
        {
          "id": "0x01",
          "name": "Josh",
          "bio": "Amazing docs",
          "attributes": [
            {
              "displayType": null,
              "traitType": null,
              "key": "custom_field",
              "value": "yes this is custom"
            }
          ],
          "followNftAddress": null,
          "metadata": "ipfs://QmSfyMcnh1wnJHrAWCBjZHapTS859oNSsuDFiAPPdAHgHP",
          "isDefault": false,
          "picture": null,
          "handle": "josh.dev",
          "coverPicture": null,
          "ownedBy": "0xD020E01C0c90Ab005A01482d34B808874345FD82",
          "dispatcher": {
            "address": "0xEEA0C1f5ab0159dba749Dc0BAee462E5e293daaF"
          },
          "stats": {
            "totalFollowers": 2,
            "totalFollowing": 1,
            "totalPosts": 1,
            "totalComments": 0,
            "totalMirrors": 0,
            "totalPublications": 1,
            "totalCollects": 6
          },
          "followModule": null
        }
      ],
      "pageInfo": {
        "prev": "{\"offset\":0}",
        "next": "{\"offset\":1}",
        "totalCount": 1
      }
    }
  }
}

Full code example

import { apolloClient } from './apollo-client';
// this is showing you how you use it with react for example
// if your using node or something else you can import using
// @apollo/client/core!
import { gql } from '@apollo/client'

const GET_PROFILES = `
  query($request: ProfileQueryRequest!) {
    profiles(request: $request) {
      items {
        id
        name
        bio
        attributes {
          displayType
          traitType
          key
          value
        }
                followNftAddress
        metadata
        isDefault
        picture {
          ... on NftImage {
            contractAddress
            tokenId
            uri
            verified
          }
          ... on MediaSet {
            original {
              url
              mimeType
            }
          }
          __typename
        }
        handle
        coverPicture {
          ... on NftImage {
            contractAddress
            tokenId
            uri
            verified
          }
          ... on MediaSet {
            original {
              url
              mimeType
            }
          }
          __typename
        }
        ownedBy
        dispatcher {
          address
          canUseRelay
        }
        stats {
          totalFollowers
          totalFollowing
          totalPosts
          totalComments
          totalMirrors
          totalPublications
          totalCollects
        }
        followModule {
          ... on FeeFollowModuleSettings {
            type
            amount {
              asset {
                symbol
                name
                decimals
                address
              }
              value
            }
            recipient
          }
          ... on ProfileFollowModuleSettings {
           type
          }
          ... on RevertFollowModuleSettings {
           type
          }
        }
      }
      pageInfo {
        prev
        next
        totalCount
      }
    }
  }
`

export const getProfiles = (request) => {
   return apolloClient.query({
    query: gql(GET_PROFILES),
    variables: {
      request
    },
  })
}
// this is showing you how you use it with react for example
// if your using node or something else you can import using
// @apollo/client/core!
import { ApolloClient, InMemoryCache, HttpLink, ApolloLink } from '@apollo/client'

const httpLink = new HttpLink({ uri: 'https://api-mumbai.lens.dev/' });

// example how you can pass in the x-access-token into requests using `ApolloLink`
const authLink = new ApolloLink((operation, forward) => {
  // Retrieve the authorization token from local storage.
  // if your using node etc you have to handle your auth different
  const token = localStorage.getItem('auth_token');

  // Use the setContext method to set the HTTP headers.
  operation.setContext({
    headers: {
      'x-access-token': token ? `Bearer ${token}` : ''
    }
  });

  // Call the next link in the middleware chain.
  return forward(operation);
});

export const apolloClient = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
})

Did this page help you?