Skip to content

Reviewing Statements

The getStatements query is used to retrieve statement data. It supports a number of search criteria and can return statements of any type. Use the getStatements query to retrieve data unless you need to obtain information that only appears on a particular form, such as mortgage interest on a 1098 or wages on a W-2. In such cases, use the query for the distinct statement object.

This page demonstrates several sample queries which can be used to retrieve statement data. The most up-to-date information about the query, including the parameters it accepts and the payload it returns, is available as part of the introspective GraphQL documentation.

Getting All Statements

The simplest form of the query retrieves all of the statements you have uploaded. Use this form of the query if you wish to retrieve all statements and you have fewer than 100 statements in the database. Such a query takes the following form:

query {
  getStatements {
    errors
    statements {
      pageInfo {
        hasNextPage
      }
      nodes {
        otxId
        uploaderId
        formType
        status
        statementValid
        recipientFirstName
        recipientLastName
        recipientEntityName
        senderName
      }
    }
  }
}

Note

When querying statements, always check the hasNextPage field of the pageInfo object to ensure you have retrieved all matching statements. If your query does not return all statements, page through the result set by making additional queries.

The code snippets below illustrate running the query. See the documentation on authentication for information about obtaining the credential data passed in the header.

# Terminate lines with \ character to allow command to span multiple lines.
# Escape quotation marks in body of mutation or query with backslashes.
# Use here document for data stream.
# Tested using the bash interpreter on Linux.
curl 'https://sandbox.ottertax.com/v2/graphql' \
  -i \
  -X POST \
  -H 'content-type:  application/json' \
  -H 'access-token:  YOUR ACCESS TOKEN' \
  -H 'client:        YOUR CLIENT ID' \
  -H 'uid:           YOUR UID' \
  -d @- <<END_DATA
    { 
      "query":"
        query {
          getStatements {
            errors
            statements {
              pageInfo {
                hasNextPage
              }
              nodes {
                otxId
                uploaderId
                formType
                status
                statementValid
                recipientFirstName
                recipientLastName
                recipientEntityName
                senderName
              }
            }
          }
        }
      "
    }
END_DATA
:: Terminate lines with ^ character to allow command to span multiple lines.
:: Precede quotation marks in body of mutation or query with triple backslashes.
:: Precede other quotation marks in data stream with single backslashes.
:: Tested using a command prompt on Windows 10.
curl "https://sandbox.ottertax.com/v2/graphql" ^
  -i ^
  -X POST ^
  -H "content-type: application/json" ^
  -H "access-token: YOUR ACCESS TOKEN" ^
  -H "client:       YOUR CLIENT ID" ^
  -H "uid:          YOUR UID" ^
  -d "{ \"query\":\" ^
        query { ^
          getStatements { ^
            errors ^
            statements { ^
              pageInfo { ^
                hasNextPage ^
              } ^
              nodes { ^
                otxId ^
                uploaderId ^
                formType ^
                status ^
                statementValid ^
                recipientFirstName ^
                recipientLastName ^
                recipientEntityName ^
                senderName ^
              } ^
            } ^
          } ^
        } ^
     \" }"
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

// This example uses version 2.9.1 of the
// open source gson library from Google.
// See https://github.com/google/gson.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

// This example uses httpclient (version 4.5.13)
// and httpcore (version 4.4.13) libraries of the
// open source Apache HttpComponents project.
// See https://hc.apache.org/index.html.
import org.apache.http.entity.StringEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

// Download the OtterTax java classes for the GraphQL
// query and mutation responses at
// https://github.com/OtterTax/graphql-java-classes
import com.ottertax.support.GetStatementsResponse;

public class StatementReviewer {
  private String endpoint = "https://sandbox.ottertax.com/v2/graphql";
  private String accessToken = "YOUR ACCESS TOKEN";
  private String client = "YOUR CLIENT ID";
  private String uid = "YOUR UID";
  private String gql =
     String.join("\n",
                 "query {",
                 "  getStatements {",
                 "    errors",
                 "    statements {",
                 "      pageInfo {",
                 "        hasNextPage",
                 "      }",
                 "      nodes {",
                 "        otxId",
                 "        uploaderId",
                 "        formType",
                 "        status",
                 "        statementValid",
                 "        recipientFirstName",
                 "        recipientLastName",
                 "        recipientEntityName",
                 "        senderName",
                 "      }",
                 "    }",
                 "  }",
                 "}");

  private String querify(String rawGraphql) {
    Gson gson = new Gson();
    return("{\"query\":" + gson.toJson(rawGraphql) + "}");
  }

  private void get() {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String response = "";

    try {
      HttpPost httpPost = new HttpPost(endpoint);
      httpPost.addHeader("content-type", "application/json");
      httpPost.addHeader("access-token", accessToken);
      httpPost.addHeader("client", client);
      httpPost.addHeader("uid", uid);

      StringEntity stringEntity = new StringEntity(querify(gql));
      httpPost.setEntity(stringEntity);
      CloseableHttpResponse httpResponse = httpClient.execute(httpPost);

      BufferedReader reader = new BufferedReader(new InputStreamReader(
          httpResponse.getEntity().getContent()));
      StringBuffer responseBuffer = new StringBuffer();
      String inputLine;
      while ((inputLine = reader.readLine()) != null) {
        responseBuffer.append(inputLine);
      }
      reader.close();
      response = responseBuffer.toString();
      int responseCode = httpResponse.getStatusLine().getStatusCode();
      if( responseCode != 200  ) {
        System.out.println("Response code from server was " + String.valueOf(responseCode) + ".");
      }
      httpResponse.close();
      httpClient.close();
    } catch(IOException e) {
      System.out.println("Error posting GraphQL.\nExiting");
      System.exit(1);
    }
    GetStatementsResponse getStatementsResponse = gson.fromJson(response, GetStatementsResponse.class);
    // Show the statements that were retrieved.
    System.out.println(gson.toJson(getStatementsResponse));
  }

  public static void main(String[] args) {
    StatementReviewer statementReviewer = new StatementReviewer();
    statementReviewer.get();
  }
}
// Using graphql-request from
// https://github.com/prisma-labs/graphql-request
// Example tested with node version 14.16.0
import { GraphQLClient, gql } from 'graphql-request'

async function main() {
  const endpoint = 'https://sandbox.ottertax.com/v2/graphql'

  const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      'access-token': 'YOUR ACCESS TOKEN',
      'client':       'YOUR CLIENT ID',
      'uid':          'YOUR UID'
    },
  })
  const query = gql`
    query {
      getStatements {
        errors
        statements {
          pageInfo {
            hasNextPage
          }
          nodes {
            otxId
            uploaderId
            formType
            status
            statementValid
            recipientFirstName
            recipientLastName
            recipientEntityName
            senderName
          }
        }
      }
    }
  `

  const data = await graphQLClient.request(query)
  console.log(JSON.stringify(data))
}

main().catch((error) => console.error(error))
<?php
// Tested with php-cli version 8.0.5.
$query =<<<'END_DATA'
  query {
    getStatements {
      errors
      statements {
        pageInfo {
          hasNextPage
        }
        nodes {
          otxId
          uploaderId
          formType
          status
          statementValid
          recipientFirstName
          recipientLastName
          recipientEntityName
          senderName
        }
      }
    }
  }
END_DATA;
$payload = array ('query' => $query);
$options = array(
  'http' => array(
    'method'  => 'POST',
    'content' => json_encode( $payload ),
    'header'=>  "Content-Type: application/json\r\n" .
                "access-token: YOUR ACCESS TOKEN\r\n" .
                "client:       YOUR CLIENT ID\r\n" .
                "uid:          YOUR UID\r\n"
    )
);

$context  = stream_context_create( $options );
$response = file_get_contents( 'https://sandbox.ottertax.com/v2/graphql',
                               false, $context );
if( $response === FALSE ) {
  echo "Call to server failed.\n";
} else {
  echo $response . "\n";
}
?>
# Using GQL from
# https://github.com/graphql-python/gql
# Tested using python version 3.8.8
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport

transport = AIOHTTPTransport(url="https://sandbox.ottertax.com/v2/graphql",
                            headers={ 'access-token': 'YOUR ACCESS TOKEN',
                                      'client':       'YOUR CLIENT ID',
                                      'uid':          'YOUR UID' })
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(
    """
      query {
        getStatements {
          errors
          statements {
            pageInfo {
              hasNextPage
            }
            nodes {
              otxId
              uploaderId
              formType
              status
              statementValid
              recipientFirstName
              recipientLastName
              recipientEntityName
              senderName
            }
          }
        }
      }
    """
)

result = client.execute(query)
print(result)
# If you wish to use a library instead, see
# https://github.com/github/graphql-client
# Tested using ruby 2.7.2.
require( 'net/http' )
require( 'uri' )
require( 'json' )

uri = URI( "https://sandbox.ottertax.com/v2/graphql" )
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
headers = { 'Content-Type': 'application/json',
            'access-token': 'YOUR ACCESS TOKEN',
            'client':       'YOUR CLIENT ID',
            'uid':          'YOUR UID' }

query = <<-END_DATA
  query {
    getStatements {
      errors
      statements {
        pageInfo {
          hasNextPage
        }
        nodes {
          otxId
          uploaderId
          formType
          status
          statementValid
          recipientFirstName
          recipientLastName
          recipientEntityName
          senderName
        }
      }
    }
  }
END_DATA
request = Net::HTTP::Post.new(uri.request_uri, headers )
request.body = {query: query}.to_json
response = http.request(request)
if( response.code == '200' )
  payload = JSON.parse( response.body )
  STDOUT.puts( payload )
else
  STDOUT.puts( "Response code was #{response.code}:\n#{response.inspect}" )
end

Getting Statements Conditionally

The getStatements query accepts several parameters so you can retrieve statements that meet only certain conditions. These parameters are:

Parameter Description Sample Value
otxIds A list of OtterTax IDs to select. ["a948985e-d69e-4755-a388-f30f88438137",
"2117c481-e7fe-4868-ab05-e74dd9717dfc"]
uploaderIds A list of uploader IDs to select. ["yZSpCJlhJs",
"kVRTlBB27m"]
formType The form type to select. Fw2
validOnly If true, select only statements that are valid. true
invalidOnly If true, select only statements that are invalid. true
status The numeric statement status to select. 110
taxYear The tax year to select. 2020
tag Select all statements whose tags include the supplied value. "review group 3"
recipientName Select all statements where any part of the recipient name matches the supplied value. "Alice Jones"
senderName Select all statements where any part of the sender name matches the supplied value. "Empire Savings Bank"

Note

Selection criteria are joined using AND. Supplying both otxIds and uploaderIds parameters, for example, means that only statements having a matching OTX ID and a matching uploader ID will be returned.

Sample Conditional Query

The following query selects only invalid statements of type 1098 that include the tag "review group 3."

query {
  getStatements(formType: F1098,
                tag: "review group 3",
                invalidOnly: true) {
    errors
    statements {
      pageInfo {
        hasNextPage
      }
      nodes {
        otxId
        uploaderId
        formType
        status
        statementValid
        recipientFirstName
        recipientLastName
        recipientEntityName
        senderName
      }
    }
  }
}

The code snippets below illustrate running the query. See the documentation on authentication for information about obtaining the credential data passed in the header.

# Terminate lines with \ character to allow command to span multiple lines.
# Escape quotation marks in body of mutation or query with backslashes.
# Use here document for data stream.
# Tested using the bash interpreter on Linux.
curl 'https://sandbox.ottertax.com/v2/graphql' \
  -i \
  -X POST \
  -H 'content-type:  application/json' \
  -H 'access-token:  YOUR ACCESS TOKEN' \
  -H 'client:        YOUR CLIENT ID' \
  -H 'uid:           YOUR UID' \
  -d @- <<END_DATA
    { 
      "query":"
        query {
          getStatements(formType: F1098,
                        tag: \"review group 3\",
                        invalidOnly: true) {
            errors
            statements {
              pageInfo {
                hasNextPage
              }
              nodes {
                otxId
                uploaderId
                formType
                status
                statementValid
                recipientFirstName
                recipientLastName
                recipientEntityName
                senderName
              }
            }
          }
        }
      "
    }
END_DATA
:: Terminate lines with ^ character to allow command to span multiple lines.
:: Precede quotation marks in body of mutation or query with triple backslashes.
:: Precede other quotation marks in data stream with single backslashes.
:: Tested using a command prompt on Windows 10.
curl "https://sandbox.ottertax.com/v2/graphql" ^
  -i ^
  -X POST ^
  -H "content-type: application/json" ^
  -H "access-token: YOUR ACCESS TOKEN" ^
  -H "client:       YOUR CLIENT ID" ^
  -H "uid:          YOUR UID" ^
  -d "{ \"query\":\" ^
        query { ^
          getStatements(formType: F1098, ^
                        tag: \\\"review group 3\\\", ^
                        invalidOnly: true) { ^
            errors ^
            statements { ^
              pageInfo { ^
                hasNextPage ^
              } ^
              nodes { ^
                otxId ^
                uploaderId ^
                formType ^
                status ^
                statementValid ^
                recipientFirstName ^
                recipientLastName ^
                recipientEntityName ^
                senderName ^
              } ^
            } ^
          } ^
        } ^
     \" }"
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

// This example uses version 2.9.1 of the
// open source gson library from Google.
// See https://github.com/google/gson.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

// This example uses httpclient (version 4.5.13)
// and httpcore (version 4.4.13) libraries of the
// open source Apache HttpComponents project.
// See https://hc.apache.org/index.html.
import org.apache.http.entity.StringEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

// Download the OtterTax java classes for the GraphQL
// query and mutation responses at
// https://github.com/OtterTax/graphql-java-classes
import com.ottertax.support.GetStatementsResponse;

public class StatementReviewer {
  private String endpoint = "https://sandbox.ottertax.com/v2/graphql";
  private String accessToken = "YOUR ACCESS TOKEN";
  private String client = "YOUR CLIENT ID";
  private String uid = "YOUR UID";
  private String gql =
     String.join("\n",
                 "query {",
                 "  getStatements(formType: F1098,",
                 "                tag: \"review group 3\",",
                 "                invalidOnly: true) {",
                 "    errors",
                 "    statements {",
                 "      pageInfo {",
                 "        hasNextPage",
                 "      }",
                 "      nodes {",
                 "        otxId",
                 "        uploaderId",
                 "        formType",
                 "        status",
                 "        statementValid",
                 "        recipientFirstName",
                 "        recipientLastName",
                 "        recipientEntityName",
                 "        senderName",
                 "      }",
                 "    }",
                 "  }",
                 "}");

  private String querify(String rawGraphql) {
    Gson gson = new Gson();
    return("{\"query\":" + gson.toJson(rawGraphql) + "}");
  }

  private void get() {
    CloseableHttpClient httpClient = HttpClients.createDefault();
    Gson gson = new GsonBuilder().setPrettyPrinting().create();
    String response = "";

    try {
      HttpPost httpPost = new HttpPost(endpoint);
      httpPost.addHeader("content-type", "application/json");
      httpPost.addHeader("access-token", accessToken);
      httpPost.addHeader("client", client);
      httpPost.addHeader("uid", uid);

      StringEntity stringEntity = new StringEntity(querify(gql));
      httpPost.setEntity(stringEntity);
      CloseableHttpResponse httpResponse = httpClient.execute(httpPost);

      BufferedReader reader = new BufferedReader(new InputStreamReader(
          httpResponse.getEntity().getContent()));
      StringBuffer responseBuffer = new StringBuffer();
      String inputLine;
      while ((inputLine = reader.readLine()) != null) {
        responseBuffer.append(inputLine);
      }
      reader.close();
      response = responseBuffer.toString();
      int responseCode = httpResponse.getStatusLine().getStatusCode();
      if( responseCode != 200  ) {
        System.out.println("Response code from server was " + String.valueOf(responseCode) + ".");
      }
      httpResponse.close();
      httpClient.close();
    } catch(IOException e) {
      System.out.println("Error posting GraphQL.\nExiting");
      System.exit(1);
    }
    GetStatementsResponse getStatementsResponse = gson.fromJson(response, GetStatementsResponse.class);
    // Show the statements that were retrieved.
    System.out.println(gson.toJson(getStatementsResponse));
  }

  public static void main(String[] args) {
    StatementReviewer statementReviewer = new StatementReviewer();
    statementReviewer.get();
  }
}
// Using graphql-request from
// https://github.com/prisma-labs/graphql-request
// Example tested with node version 14.16.0
import { GraphQLClient, gql } from 'graphql-request'

async function main() {
  const endpoint = 'https://sandbox.ottertax.com/v2/graphql'

  const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      'access-token': 'YOUR ACCESS TOKEN',
      'client':       'YOUR CLIENT ID',
      'uid':          'YOUR UID'
    },
  })
  const query = gql`
    query {
      getStatements(formType: F1098,
                    tag: "review group 3",
                    invalidOnly: true) {
        errors
        statements {
          pageInfo {
            hasNextPage
          }
          nodes {
            otxId
            uploaderId
            formType
            status
            statementValid
            recipientFirstName
            recipientLastName
            recipientEntityName
            senderName
          }
        }
      }
    }
  `

  const data = await graphQLClient.request(query)
  console.log(JSON.stringify(data))
}

main().catch((error) => console.error(error))
<?php
// Tested with php-cli version 8.0.5.
$query =<<<'END_DATA'
  query {
    getStatements(formType: F1098,
                  tag: "review group 3",
                  invalidOnly: true) {
      errors
      statements {
        pageInfo {
          hasNextPage
        }
        nodes {
          otxId
          uploaderId
          formType
          status
          statementValid
          recipientFirstName
          recipientLastName
          recipientEntityName
          senderName
        }
      }
    }
  }
END_DATA;
$payload = array ('query' => $query);
$options = array(
  'http' => array(
    'method'  => 'POST',
    'content' => json_encode( $payload ),
    'header'=>  "Content-Type: application/json\r\n" .
                "access-token: YOUR ACCESS TOKEN\r\n" .
                "client:       YOUR CLIENT ID\r\n" .
                "uid:          YOUR UID\r\n"
    )
);

$context  = stream_context_create( $options );
$response = file_get_contents( 'https://sandbox.ottertax.com/v2/graphql',
                               false, $context );
if( $response === FALSE ) {
  echo "Call to server failed.\n";
} else {
  echo $response . "\n";
}
?>
# Using GQL from
# https://github.com/graphql-python/gql
# Tested using python version 3.8.8
from gql import gql, Client
from gql.transport.aiohttp import AIOHTTPTransport

transport = AIOHTTPTransport(url="https://sandbox.ottertax.com/v2/graphql",
                            headers={ 'access-token': 'YOUR ACCESS TOKEN',
                                      'client':       'YOUR CLIENT ID',
                                      'uid':          'YOUR UID' })
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(
    """
      query {
        getStatements(formType: F1098,
                      tag: "review group 3",
                      invalidOnly: true) {
          errors
          statements {
            pageInfo {
              hasNextPage
            }
            nodes {
              otxId
              uploaderId
              formType
              status
              statementValid
              recipientFirstName
              recipientLastName
              recipientEntityName
              senderName
            }
          }
        }
      }
    """
)

result = client.execute(query)
print(result)
# If you wish to use a library instead, see
# https://github.com/github/graphql-client
# Tested using ruby 2.7.2.
require( 'net/http' )
require( 'uri' )
require( 'json' )

uri = URI( "https://sandbox.ottertax.com/v2/graphql" )
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
headers = { 'Content-Type': 'application/json',
            'access-token': 'YOUR ACCESS TOKEN',
            'client':       'YOUR CLIENT ID',
            'uid':          'YOUR UID' }

query = <<-END_DATA
  query {
    getStatements(formType: F1098,
                  tag: "review group 3",
                  invalidOnly: true) {
      errors
      statements {
        pageInfo {
          hasNextPage
        }
        nodes {
          otxId
          uploaderId
          formType
          status
          statementValid
          recipientFirstName
          recipientLastName
          recipientEntityName
          senderName
        }
      }
    }
  }
END_DATA
request = Net::HTTP::Post.new(uri.request_uri, headers )
request.body = {query: query}.to_json
response = http.request(request)
if( response.code == '200' )
  payload = JSON.parse( response.body )
  STDOUT.puts( payload )
else
  STDOUT.puts( "Response code was #{response.code}:\n#{response.inspect}" )
end