Skip to main content

Searching for Objects

A node query can fetch information about a specific object given an ID, but if you want to fetch information about multiple objects of the same type, you can specify criteria in a search query. The search query returns the fields you can use to search for objects. The available types you can search for are defined in the Search type.

Here's a typical search workflow:

  1. Specify the type of object to search and the fields you want back in the query.
  2. Specify your search criteria in the variables.
  3. POST to the GraphQL endpoint.
  4. Paginate through your results.

Here's an example transaction search:

curl \
 -H 'Content-Type: application/json' \
 -H 'Authorization: Basic BASE64_ENCODED(PUBLIC_KEY:PRIVATE_KEY)' \
 -H 'Braintree-Version: 2019-01-01' \
 -X POST https://payments.sandbox.braintree-api.com/graphql \
 -d '{
  "query": "query Search($input: TransactionSearchInput!) {
    search {
      transactions(input: $input) {
        pageInfo {
          hasNextPage
          startCursor
          endCursor
        },
        edges {
          node {
            id
            status
            amount {
              value
              currencyIsoCode
            }
          }
        }
      }
    }
  }",
  "variables": {
    "input": {
       "amount": {
         "value": {
           "greaterThanOrEqualTo": "10.00"
         }
       },
       "status": {
         "in": ["SETTLED", "VOIDED"]
       }
     }
   }
}'

Constructing Searches

To construct a search query, first select the type you'd like to search for, request the fields you want to be returned in the node field, request pageInfo which allows you to paginate through your results, and then specify the search criteria.

Search criteria are specified through input fields and generally follow one of four patterns to specify the criteria by which you would like to filter the results of your search. If you specify multiple criteria, they are logically AND'd together, so all criteria must be met in order for the search to match an object.

Ranges

Range searches support the operators is, greaterThanOrEqualTo, and lessThanOrEqualTo. The SearchRangeInput type is an example of the range criteria.

To specify transactions with 10.00 <= amount <= 1000.00 pass the following input:

"variables": {
  "input": {
     "amount": {
       "value": {
         "greaterThanOrEqualTo": "10.00",
         "lessThanOrEqualTo": "1000.00"
       }
     }
   }
 }

Timestamps

Timestamp searches support the operators greaterThanOrEqualTo and lessThanOrEqualTo. The SearchTimestampInput type is an example of the timestamp criteria.

The following would look for objects created between January 1, 2019, 6am UTC and January 3, 4pm UTC:

"variables": {
  "input": {
     "createdAt": {
       "lessThanOrEqualTo": "2019-01-03T16:00:00+00:00",
       "greaterThanOrEqualTo": "2019-01-01T06:00:00+00:00"
     }
   }
 }

Multiple Value Fields

Fields that accept multiple values support the operator in. The SearchValueInput, SearchTransactionStatusInput, and SearchDisputeTypeInput types are all examples of the multiple value field criteria.

For example, to search for transactions that have a status of either SETTLED or VOIDED you could pass the following input to the search query:

"variables": {
  "input": {
     "status": {
       "in": ["SETTLED", "VOIDED"]
     }
   }
 }

Free Text Searches

Free text searches support the operators is, isNot, startsWith, endsWith, and contains. The SearchTextInput type is an example of a free text search criteria.

For example, the following input could be provided to find Customers whose first name starts with "Jo":

"variables": {
  "input": {
     "firstName": {
       "startsWith": "Jo"
     }
   }
 }

Putting it all together

If you wanted to search for all transactions in February, 2019, greater than $100, that are SETTLED and have an orderId starting with "cat-food":

curl \
 -H 'Content-Type: application/json' \
 -H 'Authorization: Basic BASE64_ENCODED(PUBLIC_KEY:PRIVATE_KEY)' \
 -H 'Braintree-Version: 2019-01-01' \
 -X POST https://payments.sandbox.braintree-api.com/graphql \
 -d '{
  "query": "query Search($input: TransactionSearchInput!) {
    search {
      transactions(input: $input) {
        pageInfo {
          hasNextPage
          startCursor
          endCursor
        },
        edges {
          node {
            id
            status
            amount {
              value
              currencyIsoCode
            }
            orderId
          }
        }
      }
    }
  }",
  "variables": {
    "input": {
       "createdAt": {
         "greaterThanOrEqualTo": "2019-02-01T00:00:00+00:00",
         "lessThanOrEqualTo": "2019-03-01T00:00:00+00:00"
        },
       "amount": {
         "value": {
           "greaterThanOrEqualTo": "100.00"
         }
       },
       "status": {
         "in": ["SETTLED"]
       },
       "orderId": {
         "startsWith": "cat-food"
       }
     }
   }
}'

Understanding Your Results

Braintree's GraphQL API implements the Relay Cursor Connections Specification for presenting paginated search results. To read more about how connections are used throughout our API, see the Pagination and Relay Connections guide. Relay uses cursors for managing pagination, you must use a returned cursor as a parameter to access the next page of results, all of which will be logically after the cursor provided.

Here's a query to get back your transactions without any filtering (search criteria). By default, the API returns the maximum results per page, 50. Here, we've asked for just the first three results, and only the ID and transaction status:

query {
  search {
    transactions(input: {}, first: 3) {
      pageInfo {
        hasNextPage
        startCursor
        endCursor
      }
      edges {
        cursor
        node {
          id
          status
        }
      }
    }
  }
}

The server responds:

{
  "data": {
    "search": {
      "transactions": {
        "pageInfo": {
          "hasNextPage": true,
          "startCursor": "MTktMTAtMDhUMjA6MTA6MzRa",
          "endCursor": "MTktMDktMjNUMTM6NTE6MDNa"
        },
        "edges": [
          {
            "cursor": "MTktMTAtMDhUMjA6MTA6MzRa",
            "node": {
              "id": "dHJhbnNhY3Rpb25fZzN5Z2NmM2c",
              "status": "SETTLED"
            }
          },
          {
            "cursor": "MTktMDktMjNUMTM6NTc6NDha",
            "node": {
              "id": "dHJhbnNhY3Rpb25fZ2VoMnY2dmc",
              "status": "SETTLED"
            }
          },
          {
            "cursor": "MTktMDktMjNUMTM6NTE6MDNa",
            "node": {
              "id": "dHJhbnNhY3Rpb25fZDFuZDVhdzM",
              "status": "SETTLED"
            }
          }
        ]
      }
    }
  },
  "extensions": { "requestId": "D48-CkB2SQkhnw==" }
}

The objects you've searched for are contained in the list edges. Each edge is a node of the data we requested (ID and status) and a cursor representing that node's position in the edges list. In pageInfo, the startCursor is the same as the cursor for the first result, the endCursor is the same as the cursor of the last result. Since hasNextPage is true, we know there are more results. Let's ask for the next three results after endCursor:

query {
  search {
    transactions(input: {}, first: 3, after: "MTktMDktMjNUMTM6NTE6MDNa") {
      pageInfo {
        hasNextPage
        startCursor
        endCursor
      }
      edges {
        cursor
        node {
          id
          status
        }
      }
    }
  }
}

And we get the next three items.

{
  "data": {
    "search": {
      "transactions": {
        "pageInfo": {
          "hasNextPage": true,
          "startCursor": "MTktMDktMjNUMTM6NDQ6MzZa",
          "endCursor": "MTktMDktMjNUMTM6MzE6MjBa"
        },
        "edges": [
          {
            "cursor": "MTktMDktMjNUMTM6NDQ6MzZa",
            "node": {
              "id": "dHJhbnNhY3Rpb25fa21wMXBjdG0",
              "status": "SETTLED"
            }
          },
          {
            "cursor": "MTktMDktMjNUMTM6NDQ6MTda",
            "node": {
              "id": "dHJhbnNhY3Rpb25fazNtaG42ZnI",
              "status": "SETTLED"
            }
          },
          {
            "cursor": "MTktMDktMjNUMTM6MzE6MjBa",
            "node": {
              "id": "dHJhbnNhY3Rpb25fZzZremNidm0",
              "status": "SETTLED"
            }
          }
        ]
      }
    }
  },
  "extensions": {
    "requestId": "uVWGQkzkKlHd-Q=="
  }
}

Empty Results

If you make a query for which there are no results, the edges array will be empty, hasNextPage will be false, and startCursor and endCursor will be set to null. For example:

{
  "data": {
    "search": {
      "transactions": {
        "pageInfo": {
          "hasNextPage": false,
          "startCursor": null,
          "endCursor": null
        },
        "edges": [ ]
      }
    }
  },
  "extensions": {
    "requestId": "w8QZkYHDMho5gw=="
  }
}