Python Quick Start¶
This quick start guide illustrates how to add two new W-2 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
A video tutorial is available on the OtterTax videos page demonstrating how to get started with Python. 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.
# 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/")
client = Client(transport=transport, fetch_schema_from_transport=True)
query = gql(
"""
mutation {
confirmRegistration(
confirmationToken: "YOUR CONFIRMATION TOKEN",
password: "YOUR SECURE PASSWORD"
) {
message
}
}
"""
)
result = client.execute(query)
print(result)
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 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)
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.
# 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(
"""
mutation {
addFw2Statements(
statements: [
{
federalTaxWithheld: "18622.44"
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"
senderState: "NY"
senderTin: "104123456"
senderZipCode: "10282"
socialSecurityTaxWithheld: "4484.17"
socialSecurityWages: "74714.16"
tags: ["group 7", "New York"]
uploaderId: "14119"
wagesTipsOtherComp: "74714.16"
}
{
federalTaxWithheld: "9685.00"
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"
senderState: "NY"
senderTin: "104123456"
senderZipCode: "10282"
socialSecurityTaxWithheld: "2773.38"
socialSecurityWages: "44021.96"
tags: ["group 7", "New York", "send for review"]
uploaderId: "14120"
wagesTipsOtherComp: "44021.96"
}
]
) {
errors
statements {
recordNumber
statement {
federalTaxWithheld
otxId
uploaderId
recipientFirstName
recipientLastName
socialSecurityTaxWithheld
socialSecurityWages
tags
wagesTipsOtherComp
}
messages
}
}
}
"""
)
result = client.execute(query)
print(result)
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.
# 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
import json
import base64
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(
uploaderIds: [
"14119"
"14120"
]
) {
errors
statements {
nodes {
otxId
uploaderId
pdf
}
}
}
}
"""
)
result = client.execute(query)
statements = result['getStatements']['statements']['nodes']
statements_directory = './statements'
for statement in statements:
file_name = f'{statements_directory}/{statement["otxId"]}.pdf'
pdf_file = open(file_name, 'w+b')
pdf_file.write(base64.b64decode(statement['pdf']))
pdf_file.close()
Your statements are in a subdirectory called statements.
Where to Go from Here
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.