Search operations with lists

When you request a list of objects with the BILL v3 API, you can perform a range of operations in your requests. This includes filtering, sorting, and pagination. In your GET request, add all search operations as query parameters.

Filter operation

Set the field name, operator, and value in your list filters as query parameters. Both simple and compound filtering is available.

The format is filters={field_01}:{op}:{value},{field_02}:{op}:{value}.

Operators

A range of operators are available for you to filter with. See Filterable fields for information about available fields and related operators.

Operator valueNameExample
eqEqualfilters=accountType:eq:BUSINESS
neNot equalfilters=billCurrency:ne:USD
gtGreater thanfilters=createdTime:gt:"2026-12-30T00:00:00.000Z"
gteGreater than or equalfilters=updatedTime:gte:"2026-12-30T00:00:00.000Z"
ltLess thanfilters=createdTime:lt:"2026-12-30T00:00:00.000Z"
lteLess than or equalfilters=updatedTime:lte:"2026-12-30T00:00:00.000Z"
inInfilters=invoiceCurrency:in:"USD,CAD"
ninNot infilters=accountType:nin:"NONE,PERSON"
swStarts withfilters=name:sw:"Hap"
👍

Options for filtering with createdTime and updatedTime

For filtering with createdTime and updatedTime, you can set a range of ISO 8601 date-time values.

  • yyyy-MM-dd'T'HH:mm:ss.SSSX
  • yyyy-MM-dd'T'HH:mm:ss.SSS
  • yyyy-MM-dd'T'HH:mm:ss
  • yyyy-MM-dd'T'HH:mm
  • yyyy-MM-dd

Sample request

In this cURL example, the filter is set for all vendors created in September 2026. A compound filter is set with filters=createdTime:gte:"2026-09-01T00:00:00.000Z",createdTime:lt:"2026-10-01T00:00:00.000Z".

curl --request GET \
--url 'https://gateway.stage.bill.com/connect/v3/vendors?filters=createdTime:gte:"2026-09-01T00:00:00.000Z",createdTime:lt:"2026-10-01T00:00:00.000Z"' \
--header 'content-type: application/json' \
--header 'devKey: {developer_key}' \
--header 'sessionId: {session_id}'

Sort operation

Set the field name and sort order as query parameters. You can sort in the ascending (asc) or descending (desc) order. The default sorting order is ascending. Both simple and compound sorting is available.

The format is sort={field_01}:{sort_order},{field_02}:{sort_order}.

👍

Sorting order

Sorting occurs in the specified order.

Sorting examplesDescription
sort=dueDate:ascSort by dueDate in the ascending order
sort=dueDate:descSort by dueDate in the descending order
sort=dueDate,fundingAmount:descSort by dueDate in the ascending order and fundingAmount in the descending order

See Sortable fields for information about fields you can sort with.

Sample request

In this cURL example, vendors are sorted by createdTime in the descending order.

curl --request GET \
--url 'https://gateway.stage.bill.com/connect/v3/vendors?sort=createdTime:desc' \
--header 'content-type: application/json' \
--header 'devKey: {developer_key}' \
--header 'sessionId: {session_id}'

Pagination

When you perform a search, you get a maximum of 100 results with one API request. For example, you get a maximum of 100 bills with one GET /v3/bills request.

When your search response has over 100 results, the results are paginated. In this case, the response includes nextPage and prevPage values for you to navigate between the pages of results. The nextPage and prevPage values uniquely represent each page of results based on your search.

Sample request 01: Get first page of 5 results

In this cURL example, vendors are filtered by billCurrency and also sorted by createdTime in the descending order. In addition, the max query parameter is set as 5 to get 5 results per page.

The query parameters are set as filters=billCurrency:eq:USD&sort=createdTime:desc&max=5.

curl --request GET \
--url 'https://gateway.stage.bill.com/connect/v3/vendors?filters=billCurrency:eq:USD&sort=createdTime:desc&max=5' \
--header 'content-type: application/json' \
--header 'devKey: {developer_key}' \
--header 'sessionId: {session_id}'

Response 01

In the response, the first 5 results are available. A nextPage value is available for you to get the next page of results in a subsequent request.

{
  "nextPage": "{nextPage_value}",
  "results": [
    {
      // result 01
    },
    
    ...
    
    {
      // result 05
    }
  ]
}

Sample request 02: Get next page of 5 results

In this cURL example, the next page of 5 results are requested. The page query parameter is set as the nextPage value from the previous response. Since nextPage value uniquely represents a page of results based on the search, do not set any filters and sort parameters.

👍

The max value can be updated per page

You can change the max value in your subsequent request. For example, you can request a next page of 15 results with max=15.

The query parameters are set as ?page={nextPage_value}&max=5.

curl --request GET \
--url 'https://gateway.stage.bill.com/connect/v3/vendors?page={nextPage_value}&max=5' \
--header 'content-type: application/json' \
--header 'devKey: {developer_key}' \
--header 'sessionId: {session_id}'

Response 02

In the response, the next 5 results are available. Both nextPage and prevPage values are available for you to navigate between pages of results in a subsequent request.

{
  "nextPage": "{nextPage_value}",
  "prevPage": "{prevPage_value}",
  "results": [
    {
      // result 06
    },
    
    ...
    
    {
      // result 10
    }
  ]
}

Export to CSV

In this section, we showcase an example for exporting list response values to CSV. In this example, we list all bills created a day earlier. For each bill in the list response, we then export specific bill details to a CSV file.

import requests, json, csv
from datetime import date, timedelta

# Set your session ID & developer key
session_id = "set_your_session_id"
developer_key = "set_your_developer_key"

headers = {
    "Accept": "application/json",
    "Content-Type": "application/json",
    "sessionId": session_id,
    "devKey": developer_key
}

# List bills created each day
yesterday = date.today() - timedelta(days=1)
yesterday = yesterday.strftime("%Y-%m-%dT%H:%M:%S.%jZ")

today = date.today()
today = today.strftime("%Y-%m-%dT%H:%M:%S.%jZ")

response_json = []
max_value = 20
filterquery = "createdTime:gte:\"" + yesterday + "\",createdTime:lt:\"" + today + "\""

listbills_url = f'https://gateway.stage.bill.com/connect/v3/bills?max={max_value}&filters={filterquery}'
listbills_response = requests.get(listbills_url, headers=headers)

nextpage_value = json.loads(listbills_response.text)['nextPage']
if listbills_response.text != '[]':
    results = json.loads(listbills_response.text)['results']
    response_json.extend(results)

while True:
    listmorebills_url = f'https://gateway.stage.bill.com/connect/v3/bills?max={max_value}&page={nextpage_value}'
    listmorebills_response = requests.get(listmorebills_url, headers=headers)
    if "nextPage" in json.loads(listmorebills_response.text):
        nextpage_value = json.loads(listmorebills_response.text)['nextPage']
        results = json.loads(listmorebills_response.text)['results']
        response_json.extend(results)
    else:
        break

fields_to_export = ['id', 'vendorId', 'dueDate', 'createdTime']

with open('data.csv', 'w', newline='') as csv_file:
    writer = csv.DictWriter(csv_file, fieldnames=fields_to_export)
    writer.writeheader()
    for json_obj in response_json:
        row_data = {field: json_obj[field] for field in fields_to_export}
        writer.writerow(row_data)
// Requires "type": "module" in your package.json
import fetch from 'node-fetch';
import { createObjectCsvWriter } from 'csv-writer';
import { format, subDays } from 'date-fns';

// Set your session ID & developer key
const session_id = "set_your_session_id";
const developer_key = "set_your_developer_key";

// Headers for the API requests
const headers = {
  "Accept": "application/json",
  "Content-Type": "application/json",
  "sessionId": session_id,
  "devKey": developer_key
};

// Set the date range
const yesterday = format(subDays(new Date(), 1), 'yyyy-MM-dd');
const today = format(new Date(), 'yyyy-MM-dd');

// Set the filter query
const max_value = 20;
const filterquery = `createdTime:gte:"${yesterday}",createdTime:lt:"${today}"`;

let listbills_url = `https://gateway.stage.bill.com/connect/v3/bills?max=${max_value}&filters=${filterquery}`;

let response_json = [];

async function fetchBillsAndWriteCSV() {
  try {
    // Step 1: Get the first page of bills
    let listbills_response = await fetch(listbills_url, {
      method: 'GET',
      headers: headers
    });
    let listbills_result = await listbills_response.json();

    // Print the response
    console.log("API Response:", JSON.stringify(listbills_result, null, 2));

    // Check if the response contains results
    if (listbills_result.results && listbills_result.results.length > 0) {
      console.log("Results found:", listbills_result.results.length);
      response_json.push(...listbills_result.results);

      let nextpage_value = listbills_result.nextPage;

      // Step 2: Continue getting a list of bills if there is a next page
      while (nextpage_value) {
        const listmorebills_url = `https://gateway.stage.bill.com/connect/v3/bills?max=${max_value}&page=${nextpage_value}`;
        const listmorebills_response = await fetch(listmorebills_url, {
          method: 'GET',
          headers: headers
        });
        const listmorebills_result = await listmorebills_response.json();

        // Print the next page of responses
        console.log("Next page response:", JSON.stringify(listmorebills_result, null, 2));

        if (listmorebills_result.results) {
          response_json.push(...listmorebills_result.results);
        }

        nextpage_value = listmorebills_result.nextPage || null;
      }
    } else {
      console.log("No results found in the initial API request.");
    }

    // Step 3: Write the list of bills in a CSV file
    const fields_to_export = ['id', 'vendorId', 'dueDate', 'createdTime'];
    const csvWriter = createObjectCsvWriter({
      path: 'data.csv',
      header: fields_to_export.map(field => ({ id: field, title: field }))
    });

    await csvWriter.writeRecords(response_json.map(json_obj => {
      const row_data = {};
      fields_to_export.forEach(field => {
        row_data[field] = json_obj[field];
      });
      return row_data;
    }));

    console.log("CSV file 'data.csv' has been written successfully.");

  } catch (error) {
    console.error("Error occurred:", error.message);
  }
}

// Call the fetchBillsAndWriteCSV() function
fetchBillsAndWriteCSV();