Skip to content

Ruby Quick Start

This quick start guide illustrates how to add two new 1099-NEC statements to the OtterTax API and download PDF versions of the statements. Before starting, you should create an account on the sanbdbox and have your username and password handy.

Other Resources

Reader with book

A video tutorial is available on the OtterTax videos page demonstrating how to get started with Ruby. Our Github page provides full source code for the tutorial.

Confirming your registration

After registering an account in the sandbox or the production system, you need to confirm your registration. Run the code below, substituting your confirmation token and password where indicated. If successful, the API will respond with a message indicating that your registration confirmation succeeded.

# Tested using ruby 2.7.2.
require( 'net/http' )
require( 'uri' )
require( 'json' )

query = <<-END_QUERY
mutation {
confirmRegistration(
  confirmationToken: "YOUR CONFIRMATION TOKEN",
  password: "YOUR SECURE PASSWORD"
) {
    message
  }
}
END_QUERY

uri = URI( 'https://sandbox.ottertax.com/v2/graphql' )
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new( uri.request_uri,
                              {'Content-Type': 'application/json'} )
request.body = {query: query}.to_json
response = http.request(request)
if( response.code == '200' )
  json = JSON.parse( response.body )
  message = json.dig( 'data', 'confirmRegistration', 'message' )
  STDOUT.puts( message )
else
  STDOUT.puts( "Response code was #{response.code}:\n#{response.inspect}" )
end

Obtaining an Authentication Token

The API requires authentication for running queries and mutations and looks for authentication information in the request headers. To obtain the necessary header data, run the program below, substituting your email address and password where indicated. Save the output as we will use it in the next steps.

# Tested using ruby 2.7.2.
require( 'net/http' )
require( 'uri' )
require( 'json' )

uri = URI( "https://sandbox.ottertax.com/v2/auth/sign_in" )
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Post.new( uri.request_uri,
                                { 'Content-Type': 'application/json' } )
request.body = JSON.generate( {'email' =>   'YOUR LOGIN EMAIL',
                              'password' => 'YOUR PASSWORD'} )
response = http.request(request)
if( response.code == '200' )
  STDOUT.puts( "\nCredential:" )
  STDOUT.puts( "  access-token:  #{response['access-token']}" )
  STDOUT.puts( "  client:        #{response['client']}" )
  STDOUT.puts( "  uid:           #{response['uid']}" )
else
  STDOUT.puts( "Response code was #{response.code}:\n#{response.inspect}" )
end

Adding Statements

Once you've received your authentication credential, you're ready to add statements. Run the code below to add the two sample statements. Substitute the access token, client ID, and user ID you received in the last step where appropriate.

# 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
  mutation {
    addF1099necStatements(
      statements: [
        {
          nonemployeeComp: "10318.62"
          recipientAddress1: "784 East 77th Street"
          recipientCity: "New York"
          recipientFirstName: "Leif"
          recipientLastName: "Babson"
          recipientState: "NY"
          recipientTin: "200213492"
          recipientZipCode: "10162"
          senderAddress1: "406 Chambers Street"
          senderCity: "New York"
          senderName: "Empire Savings Bank"
          senderPhoneNumber: "2125557318"
          senderState: "NY"
          senderTin: "104123456"
          senderZipCode: "10282"
          tags: ["group 7", "New York"]
          uploaderId: "14121"
        }
        {
          nonemployeeComp: "6370.97"
          recipientAddress1: "617 West 53rd Street"
          recipientAddress2: "Apartment 1022"
          recipientCity: "New York"
          recipientFirstName: "Anjelica"
          recipientLastName: "Heximer"
          recipientState: "NY"
          recipientTin: "200223492"
          recipientZipCode: "10019"
          senderAddress1: "406 Chambers Street"
          senderCity: "New York"
          senderName: "Empire Savings Bank"
          senderPhoneNumber: "2125557318"
          senderState: "NY"
          senderTin: "104123456"
          senderZipCode: "10282"
          tags: ["group 7", "New York", "send for review"]
          uploaderId: "14122"
        }
      ]
    ) {
      errors
      statements {
        recordNumber
        statement {
          otxId
          uploaderId
          recipientFirstName
          recipientLastName
          tags
        }
        messages
      }
    }
  }
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

Downloading PDFs

After you've uploaded statement data, you can download PDF versions of the statements. Use the code below, again substituting the access token, client ID, and user ID you received in the last step where indicated.

# 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' )
require( 'base64' )

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_QUERY
  query {
    getStatements(
      uploaderIds: [
        "14121"
        "14122"
      ]
    ) {
      errors
      statements {
        nodes {
          otxId
          uploaderId
          pdf
        }
      }
    }
  }
END_QUERY

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Post.new(uri.request_uri, headers )
request.body = {query: query}.to_json
response = http.request(request)
unless( response.code == '200' )
  STDOUT.puts( "Response code was #{response.code}." )
  exit
end
resp = JSON.parse( response.body )
statements = resp.dig( 'data', 'getStatements', 'statements', 'nodes' )
statements_directory = './statements'
statements.each do |statement|
  file_name = "#{statements_directory}/#{statement.dig( 'otxId' )}.pdf"
  File.open( file_name, 'wb' ) do |f|
    f.write( Base64.decode64( statement.dig( 'pdf' ) ) )
  end
end

Your statements are in a subdirectory called statements.

Where to Go from Here

Directional indicators

If you need to make changes to statements after they've been uploaded, you can use the update mutation.

If you're using the production version of the API, you can remove the watermark from statements by finalizing them.

The production system also allows you to submit statements to the IRS to meet your filing requirements.