Authentication¶
In order to access the core functionality of the OtterTax API, you must be authenticated. The API performs authentication by checking the HTTP headers for three values: access-token, client, and uid. These three values must be present in every call you make to the API or the call will fail.
To get a credential which includes these three values, send a request to the endpoint v2/auth/sign_in
with a JSON payload as follows:
"email": "<YOUR LOGIN EMAIL>",
"password": "<YOUR PASSWORD>"
The code snippets below illustrate how to get your credential in several different languages.
# Terminate lines with \ character to allow command to span multiple lines.
# Escape quotation marks in data stream with single backslashes.
# Tested using the bash interpreter on Linux.
curl 'https://sandbox.ottertax.com/v2/auth/sign_in' \
-i \
-X POST \
-H 'content-type: application/json' \
-d "{ \"email\": \"YOUR LOGIN EMAIL\", \"password\": \"YOUR PASSWORD\" }"
# Output contains values for access-token, client, and uid
:: Terminate lines with ^ character to allow command to span multiple lines.
:: Escape quotation marks in data stream with single backslashes.
:: Tested using a command prompt on Windows 10.
curl "https://sandbox.ottertax.com/v2/auth/sign_in" ^
-i ^
-X POST ^
-H "content-type: application/json" ^
-d "{ \"email\": \"YOUR LOGIN EMAIL\", \"password\": \"YOUR PASSWORD\" }"
:: Output contains values for access-token, client, and uid
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
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;
import com.ottertax.support.Credential;
public class CredentialFetcher {
private String loginData = "{ \"email\": \"YOUR LOGIN EMAIL\",\n" +
"\"password\": \"YOUR PASSWORD\" }\n";
private String endpoint = "https://sandbox.ottertax.com/v2/auth/sign_in";
private void getCredential() {
CloseableHttpClient httpClient = HttpClients.createDefault();
Credential credential = new Credential();
try {
HttpPost httpPost = new HttpPost(endpoint);
httpPost.addHeader("Content-Type", "application/json");
StringEntity stringEntity = new StringEntity(loginData);
httpPost.setEntity(stringEntity);
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
int responseCode = httpResponse.getStatusLine().getStatusCode();
boolean headersPresent = (httpResponse.containsHeader("access-token") &&
httpResponse.containsHeader("client") &&
httpResponse.containsHeader("uid"));
if( responseCode == 200 && headersPresent ) {
String accessToken = httpResponse.getFirstHeader("access-token").getValue();
String client = httpResponse.getFirstHeader("client").getValue();
String uid = httpResponse.getFirstHeader("uid").getValue();
credential = new Credential(accessToken, client, uid);
} else {
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();
System.out.println("Error retrieving credential. Status code was " + String.valueOf(responseCode) + "." );
System.out.println(responseBuffer.toString());
System.out.println("Exiting.");
System.exit(1);
}
httpResponse.close();
httpClient.close();
} catch(IOException e) {
System.out.println("Error retrieving credential.\nExiting");
System.exit(1);
}
// Print a JSON format version of the credential.
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(credential));
}
public static void main(String[] args) {
CredentialFetcher credentialFetcher = new CredentialFetcher();
credentialFetcher.getCredential();
}
}
// If using node, be sure to install and require node-fetch.
// Example tested with node version 14.16.0
const fetch = require("node-fetch");
const data = { email: "YOUR LOGIN EMAIL",
password: "YOUR PASSWORD" };
fetch( "https://sandbox.ottertax.com/v2/auth/sign_in",
{ method: "POST",
headers: {"content-type": "application/json"},
body: JSON.stringify(data) })
.then(response => {
const accessToken = response.headers.get('access-token');
const client = response.headers.get('client');
const uid = response.headers.get('uid');
console.log( 'access-token: ', accessToken );
console.log( 'client: ', client );
console.log( 'uid: ', uid );
})
.catch(err => console.log(err));
<?php
// Tested with php-cli version 8.0.5.
$data = array( 'email' => 'YOUR LOGIN EMAIL',
'password' => 'YOUR PASSWORD' );
$options = array(
'http' => array(
'method' => 'POST',
'content' => json_encode( $data ),
'header'=> "Content-Type: application/json\r\n"
)
);
$context = stream_context_create( $options );
$response = get_headers( 'https://sandbox.ottertax.com/v2/auth/sign_in',
1, $context );
if( $response === FALSE ) {
print "Call to server failed.\n";
} else {
print "access-token: ${response['access-token']}\n";
print "client: ${response['client']}\n";
print "uid: ${response['uid']}\n";
}
?>
# Tested using python version 3.8.8
import urllib.request
import json
url = "https://sandbox.ottertax.com/v2/auth/sign_in"
data = {
"email": "YOUR LOGIN EMAIL",
"password": "YOUR PASSWORD"
}
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
body = json.dumps(data).encode("utf-8")
try:
req = urllib.request.Request(url, body, headers)
with urllib.request.urlopen(req) as f:
info = f.info()
print(f"access-token: {info['access-token']}")
print(f"client: {info['client']}")
print(f"uid: {info['uid']}")
except Exception as e:
print(e)
# 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
Before moving on, you may wish to test your authentication by accessing a protected query.