Skip to content

API Design Philosophy

Understanding a few conceptual points regarding the design of the API greatly facilitates working with it.

Object Types

Broadly speaking, there are two object types in the API: a generic statement object and distinct statement objects.

Generic statement object. The generic statement object encompasses all supported statements, meaning that, for example, 1098 statements, 1099-DIV statements and 3921 statements can all be accessed through the generic statement object. The generic statement object includes only those fields that are common to all statements, like sender and recipient information, the statement status, and the PDF version of the statement.

Distinct statement object. Each supported statement also has a distinct statement object. These objects include all of the information in the generic statement object plus all of the information that only appears on that particular statement. To use form 1098 as an example, the mortgageInterest field is part of the distinct statement object but not part of the generic statement object because mortgageInterest appears only on form 1098, not on other statements.

Whenever possible, queries and mutations are performed against the generic object. This means that operations performed on multiple statement types can be performed with a single API call. The deleteStatements mutation, for instance, supports deleting statements of any type. Similarly, statements of varying types can be downloaded or finalized using a single mutation.

There are three operations which must be performed against the distinct statement object:

  • Adding statements. Each supported statement has its own method for uploading data, like the addF1098Statements mutation.
  • Updating statements. Similarly, each statement has its own method for updating data, like the updateF1098Statements mutation.
  • Fetching statements. Finally, each statement has a query for fetching statement-specific data, like getF1098Statements. If you do not need statement-specific data (if you only wish to get PDF versions of statements and statement statuses, for example), you should use the getStatements query instead, which operates on the generic statement object.

All other operations are performed against the generic statement object.

Sender and Recipient Names

Forms issued by the Internal Revenue Service and the Social Security Administration use different names for the entity that issues the statement and the individual or entity that receives it. On form 1098, the sender is referred to as recipient/lender, and the recipient is referred to as payer/borrower. On W-2s, the sender is employer and the recipient is employee.

To facilitate interacting with statement data, the OtterTax API always refers to the sender as sender and the recipient as recipient. This nomenclature extends to field names, so the fields for taxpayer identification numbers (TINs) on form 1098 are senderTin and recipientTin, not lenderTin and borrowerTin. The names for the sender and recipient as they appear on the form are available as part of the statement definitions query.


Each statement can be identified in the API using several fields.

  • The OtterTax ID (otxId). The OtterTax ID is automatically assigned by OtterTax and is unique across all statements. The OtterTax ID is returned by the various add mutations, so you can capture it and use it in future operations. The OtterTax ID takes the form of an immutable universally unique identifier (UUID).
  • The uploader ID (uploaderId). The uploader ID is assigned by you, the uploader. The uploader ID is not required but its use is strongly encourgaged. Any text string may be used as an uploader ID, but uploader IDs must be unique across all statements. The IDs of deleted statements can be re-used, and uploader IDs can be changed by using an appropriate update mutation.
  • Tags. Each statement can also have a set of tags associated with it. Tags can be any text string. Each statement can have zero or more tags, and the same tag can be shared among multiple statements. Tags can be updated by using an update mutation.


Do not use nine-digit strings as uploader IDs or tags. Such strings are typically taxpayer IDs (SSNs or EINs) and should not be used for security reasons. Any nine-digit string used as an uploader ID or a tag will be automatically deleted.
Obviously, you can work around this restriction. Don't. It's a security risk.


Statement validation is performed asynchronously on statements automatically after they are uploaded or modified. This has several implications.

  • No validation is performed on statements when they are initially uploaded. Even a statement with no data at all is permitted, but, for obvious reasons, this is discouraged. At a minimum, you should include an uploaderId to facilitate retrieving and manipulating the statement later.
  • You can add statement data incrementally. Since statements are not validated when they are initally added, you can create sparsely populated statements and add data as it becomes available. For example, if you're creating 1099-NECs, you can upload statements with sender and recipient data and add amounts for nonemployee compensation later.
  • You should always check whether statements are valid before attempting to finalize them. The getStatements query supports filtering statements by their valid or invalid status. The API returns an error if you attempt to finalize statements that are invalid.