GraphQL · Growth Intelligence

GetUsers

Fetch a paginated, filtered, and sorted list of users enriched with acquisition, engagement, and demographic data — to segment your user base, build cohorts, and power user-level personalization.

API details

PropertyValue
EndpointPOST /growth-intelligence
ProtocolGraphQL over HTTP
Authenticationx-api-key header
Content-Typeapplication/json
Operationquery GetUsers
Response formatJSON

What you send

Operation query GetUsers($input: GetUsersRequest!). Every field is optional — send an empty input to get the first page of all users.

FieldTypeRequiredDescription
filters[Filter!]NoConditions a user must match, all ANDed together. Details →
segmentIdStringNoApply a saved segment's filters (by id or system name). Details →
sortSortNoOrder results by one field. Details →
paginationPaginationNoPage number and size. Defaults to page 1, size 10. Details →

What you get

A GetUsersResponse — the matching users for the requested page:

{
  "data": {
    "getUsers": {
      "user": [ User, … ],     // matching users for this page
      "message": "success"      // optional status note; may be omitted
    }
  }
}

Each User nests its fields under acquisition, engagement, and demographics, plus an account list. The User fields table lists every path, its type, and whether you can filter or sort on it.

User fields

Every field on User, its type, and whether it can be used as a filters[].key or sort.key. Fields marked No (including all account.* paths) are still returned in the response — they just can't drive filtering or sorting.

Basic
PathLabelFilterSortTypeDescriptionExample
idUser IDYesNoString!Unique user identifier"usr_abc123"
nameName (user)YesYesString!User display name"Alice Johnson"
emailEmailYesYesString!User email address"alice@acme.com"
Account
PathLabelFilterSortTypeDescriptionExample
accountAccountsNoNo[UserAccount!]CRM accounts linked to the user (empty array or null when none). Matches repeated account rows from the accounts service.[]
account.idAccount IDNoNoString!Id on each element of account[] (not a separate filter path; use User fields table for filter keys)."acc_xyz789"
account.nameAccount nameNoNoString!Display name on each account[] element."Acme Corp"
account.sourceAccount sourceNoNoString!Source stream on each account[] element."ThriveStack"
account.timestampAccount timestampNoNoString!Association timestamp on each account[] element."2024-01-10T09:00:00Z"
Status
PathLabelFilterSortTypeDescriptionExample
enrichedEnrichedYesYesBoolean!Whether enrichment data is availabletrue
softDeletedSoft deletedYesYesBoolean!Whether the user is soft-deletedfalse
sourceSourceYesYesString!User data source stream"ThriveStack"
timeToHardDeleteTime to hard deleteYesYesFloat!Days remaining until permanent deletion25.5
trackedTrackedYesYesBoolean!Whether a creation event was receivedtrue
Acquisition
PathLabelFilterSortTypeDescriptionExample
acquisition.abuseRuleResultAbuse rule resultNoNo[AbuseRuleResult!]!Per-rule abuse evaluation (query only)[{ "passed": true, "ruleId": "r1" }]
acquisition.abuseStatusAbuse statusYesYesString!Abuse classification"clean"
acquisition.initialUtmCampaignInitial UTM campaignYesYesString!UTM campaign from first touch"spring-launch"
acquisition.initialUtmContentInitial UTM contentYesYesString!UTM content from first touch"hero"
acquisition.initialUtmMediumInitial UTM mediumYesYesString!UTM medium from first touch"cpc"
acquisition.initialUtmSourceInitial UTM sourceYesYesString!UTM source from first touch"google"
acquisition.initialUtmTermInitial UTM termYesYesString!UTM term from first touch"product"
acquisition.isInvitedIs invitedYesYesBoolean!Whether user was invited by another usertrue
acquisition.signedUpOnSigned up onYesYesString!Signup date (ISO)"2024-01-10T09:00:00Z"
acquisition.timeToSignupDaysTime to signup (days)YesYesFloat!Days from first touch to signup4.5
acquisition.touchpointsToSignupTouchpoints to signupYesYesInt!Marketing touchpoints before signup3
Engagement
PathLabelFilterSortTypeDescriptionExample
engagement.isActiveIs activeYesYesBoolean!Active in last 30 daystrue
engagement.lastActiveAtLast active atYesYesString!Last activity timestamp"2024-01-22T11:30:00Z"
engagement.latestSigninTimestampLatest sign-inYesYesString!Most recent sign-in timestamp"2024-01-22T08:45:00Z"
engagement.totalSignInsTotal sign-insYesYesInt!Cumulative sign-in count47
Demographics
PathLabelFilterSortTypeDescriptionExample
demographics.avatarAvatarYesNoString!Avatar URL"https://cdn.example.com/a.png"
demographics.cityCityYesYesString!City"San Francisco"
demographics.countryCountryYesYesString!Country"United States"
demographics.countryCodeCountry codeYesYesString!ISO country code"US"
demographics.emailProviderEmail providerYesYesString!Email provider domain"gmail.com"
demographics.employmentDomainEmployment domainYesYesString!Employer company domain"acme.com"
demographics.employmentNameEmployment nameYesYesString!Company the user works at"Acme Corp"
demographics.employmentRoleEmployment roleNoNoString!Broad job role / function"product"
demographics.employmentSeniorityEmployment seniorityYesYesString!Seniority level"senior"
demographics.employmentSubRoleEmployment sub-roleYesYesString!Granular job sub-role"pm"
demographics.employmentTitleEmployment titleYesYesString!Job title"Head of Product"
demographics.facebookHandleFacebook handleYesNoString!Facebook handle"alice.j"
demographics.firstNameFirst nameYesYesString!First name (enriched)"Alice"
demographics.fullNameFull nameYesYesString!Full name from enrichment"Alice Johnson"
demographics.githubHandleGitHub handleYesNoString!GitHub username"alice"
demographics.lastNameLast nameYesYesString!Last name (enriched)"Johnson"
demographics.linkedinHandleLinkedIn handleYesNoString!LinkedIn profile handle"in/alice"
demographics.locationLocationNoNoString!Full location string"San Francisco, CA"
demographics.phonePhoneYesNoString!Phone number(s)"+1-415-555-0199"
demographics.stateStateYesYesString!State / province"California"
demographics.stateCodeState codeYesYesString!State code"CA"
demographics.timeZoneTime zoneYesYesString!IANA time zone"America/Los_Angeles"
demographics.twitterHandleTwitter handleYesNoString!Twitter/X handle"@alice"

Input fields in detail

The shape and rules for each GetUsersRequest field.

filters · optional · array

An array of filter objects. All filters are ANDed: a user must satisfy every filter. Each object has:

{
  "key": "",
  "operator": "equals | not_equals | greater_than | less_than | greater_than_or_equal | less_than_or_equal",
  "value": ""
}

value is always a string and is coerced server-side.

Operators

OperatorSymbolDescriptionExample
equals=Exact matchkey: "acquisition.abuseStatus", value: "clean"
not_equalsExcludes the given valuekey: "engagement.isActive", value: "false"
greater_than>Numeric or date comparison (exclusive)key: "engagement.totalSignIns", value: "10"
less_than<Numeric or date comparison (exclusive)key: "engagement.totalSignIns", value: "3"
greater_than_or_equalNumeric or date comparison (inclusive)key: "engagement.totalSignIns", value: "5"
less_than_or_equalNumeric or date comparison (inclusive)key: "engagement.totalSignIns", value: "100"

segmentId · optional · string

Apply a saved user segment's filters instead of (or together with) inline filters — both are ANDed. Pass the segment's id or system name (list them with GetSegments). Curated segments are not supported and return an error.

{ "segmentId": "active_users" }

sort · optional · object

Sort by exactly one field per request. sort.key must be a path whose Sort column is Yes in the User fields table above.

{
  "key": "",
  "direction": "asc" | "desc"
}

Tip: Sort by engagement.totalSignIns desc for most active users, acquisition.signedUpOn desc for newest signups, or demographics.employmentSeniority asc by seniority.

pagination · optional · object

Page-based pagination. Defaults to page 1, size 10 if omitted. size max 100.

{
  "number": 1,
  "size": 25
}

Increment number until the returned user array is empty.

Example request

Active users with more than 5 sign-ins and clean abuse status, ordered by sign-in count descending.

GraphQL query

query GetUsers($input: GetUsersRequest!) {
  getUsers(input: $input) {
    message
    user {
      id
      name
      email
      account {
        id
        name
        source
        timestamp
      }
      source
      tracked
      enriched
      softDeleted
      timeToHardDelete
      acquisition {
        signedUpOn
        isInvited
        abuseStatus
        touchpointsToSignup
        timeToSignupDays
        initialUtmSource
        initialUtmMedium
        initialUtmCampaign
        initialUtmTerm
        initialUtmContent
      }
      engagement {
        isActive
        lastActiveAt
        totalSignIns
        latestSigninTimestamp
      }
      demographics {
        firstName
        lastName
        employmentTitle
        employmentRole
        employmentSeniority
        city
        country
        timeZone
      }
    }
  }
}

Variables (JSON)

{
  "input": {
    "filters": [
      { "key": "engagement.isActive", "operator": "equals", "value": "true" },
      { "key": "engagement.totalSignIns", "operator": "greater_than", "value": "5" },
      { "key": "acquisition.abuseStatus", "operator": "equals", "value": "clean" }
    ],
    "sort": { "key": "engagement.totalSignIns", "direction": "desc" },
    "pagination": { "number": 1, "size": 25 }
  }
}

cURL

curl --location 'https://api.app.thrivestack.ai/growth-intelligence' \\
--header 'content-type: application/json' \\
--header 'x-api-key: YOUR_API_KEY' \\
--data '{
  "query": "query GetUsers($input: GetUsersRequest!) { getUsers(input: $input) { message user { id name email } } }",
  "variables": {
    "input": {
      "filters": [
        { "key": "engagement.isActive", "operator": "equals", "value": "true" },
        { "key": "engagement.totalSignIns", "operator": "greater_than", "value": "5" },
        { "key": "acquisition.abuseStatus", "operator": "equals", "value": "clean" }
      ],
      "sort": { "key": "engagement.totalSignIns", "direction": "desc" },
      "pagination": { "number": 1, "size": 25 }
    }
  }
}'

Example response

Matching users are under data.getUsers.user (array). message may be "success" or omitted depending on the server.

{
  "data": {
    "getUsers": {
      "message": "success",
      "user": [
        {
          "id": "usr_abc123",
          "name": "Alice Johnson",
          "email": "alice@acme.com",
          "account": [
            { "id": "acc_xyz789", "name": "Acme Corp", "source": "ThriveStack", "timestamp": "2024-01-10T09:00:00Z" }
          ],
          "source": "ThriveStack",
          "tracked": true,
          "enriched": true,
          "softDeleted": false,
          "timeToHardDelete": 0,
          "acquisition": {
            "signedUpOn": "2024-01-10T09:00:00Z",
            "isInvited": true,
            "abuseStatus": "clean",
            "touchpointsToSignup": 3,
            "timeToSignupDays": 4.5,
            "initialUtmSource": "google",
            "initialUtmMedium": "cpc",
            "initialUtmCampaign": "spring-launch"
          },
          "engagement": {
            "isActive": true,
            "lastActiveAt": "2024-01-22T11:30:00Z",
            "totalSignIns": 47,
            "latestSigninTimestamp": "2024-01-22T08:45:00Z"
          },
          "demographics": {
            "firstName": "Alice",
            "lastName": "Johnson",
            "employmentTitle": "Head of Product",
            "employmentRole": "product",
            "employmentSeniority": "senior",
            "city": "San Francisco",
            "country": "United States",
            "timeZone": "America/Los_Angeles"
          }
        }
      ]
    }
  }
}

Tips and best practices

  • Filter values are always strings — use "true" / "false" for booleans and numeric strings for numbers; the server coerces them.
  • All filters are ANDed. Use separate filter objects for each condition (e.g. active and 10+ sign-ins).
  • Account on the user record: select account { id name source timestamp } (a list of UserAccount). account.* can't be filtered or sorted — narrow with email or demographics.employmentDomain instead, then refine client-side.
  • Organic power users: e.g. acquisition.isInvited equals "false" with high engagement.totalSignIns.
  • Paginate by incrementing pagination.number until user is empty.