Skip to content
Terry Carroll edited this page Jul 19, 2021 · 3 revisions

Plumage - Access data from the USPTO's TSDR system.

Plumage is a module, available for Pyton or .Net (C#, VisualBasic .Net, C++/CLI) to allow easy access to the U.S. Patent and Trademark Office's Trademark Status & Document Retrieval (TSDR) system.

Plumage uses the USPTO's TSDR Data API. Beginning October 2, 2020, the USPTO requires that you register and obtain an API key to use the API, including via Plumage. This requirement is imposed by the USPTO, not by Plumage, although Plumage includes support for the API key.

The documentation below covers both the Python implementation (Plumage-py) and the .NET implmentation (Plumage-dotnet, written in C#). The .NET implmentation is intneded to support any .NET langage. For VisualBasic .NET and C++/CLI, see the Basic examples and adjust accordingly. F# support has not been tested, but is believed to work.

The phrase "None/null" when used below refers to None in Plumage-py and null in Plumage-dotnet.

The module defines the following items:

class plumage.TSDRReq

The class that is used to initiate a TSDR request to the USPTO server. After invoking a TSDR call, it includes a TSDRMap object that provides information about the specified trademark registration or application. See section TSDRReq for a description.

class plumage.TSDRMap

The class that encapsulates the parsed information from a TSDR query. See section TSDRMap for a description of its contents.

Objects

TSDRReq

To use Plumage, first create a TSDRReq object as follows.

Plumage-py:

        t = plumage.TSDRReq()

Plumage-dotnet (C#; see Basic examples for other .NET languages):

        Plumage.TSDRReq t = new Plumage.TSDRReq();

The resulting TSDRReq object t can then be used to obtain data from the PTO. Typically, the only methods needed are SetAPIKey (to specify the API key used by TSDR to validate the request); getTSDRInfo (to actually make the TSDR request); and possibly setPTOFormat (if you need ZIP or image data), SetIntervalTime (to change the length of pauses between TSDR calls if fetching ZIP files); and GetMetainfo (to get information, such as release-level, about Plumage). Other methods are provided to provide for more specific control, but normally will not be needed.

TSDRReq methods

TSDRReq provides the following methods.

t.getTSDRInfo(identifier[, tmtype])

  • Call TSDR to get information associated with the trademark record indicated and provide a TSDRMap object with dictionaries of data about the mark
  • identifier: a string of digits identifying the number of trademark record to be retrieved.
  • tmtype: a one-character string indicating what type of trademark record is requested:
    • 's': the identifier is a string of eight digits identifying the application serial number of the record to be retrieved. For example, to obtain information on application ser. no 75/181,334, use getTSDRInfo("75181334", "s").
    • 'r': the identifier is a string of seven digits identifying the registration number of the record to be retrieved. For example, to obtain information on registration no. 2,564,831, use getTSDRInfo("2564831", "r").
  • If tmtype is not specified, identifier is the name of a local file that will be read instead of making a call to TSDR. This option is normally used only for development and testing.
  • t.getTSDRInfo() sets the following fields: XMLData, XMLDataIsValid, CSVData, CSVDataIsValid, TSDRData, TSDRDataIsValid, ErrorCode and ErrorMessage. In addition, if setPTOFormat("ZIP") was specified, it also sets ZipData, as well as ImageThumb and ImageFull if data for those images is present in the ZIP file provided by the USPTO.
  • If there are errors, not all fields may be set. The fields XMLDataIsValid, CSVDataIsValid and TSDRDataIsValid may be used to determine which data fields have been reliably set.
  • getTSDRInfo is the standard way of using Plumage; Other then a one-time call to setAPIKey, getTSDRInfo will nearly always be the only method you will need to call after creating the TSDRReq object.
  • For those interested in the details, t.getTSDRInfo() is equivalent to the following pseudocode:
        t.getXMLData(identifier, tmtype)     # Fetch the XML from the PTO
        if t.XMLDataIsValid
            t.getCSVData()                   # Parse the XML into key-value comma-separated values
            if t.CSVDataIsValid
                t.getTSDRData()              # Convert the key-value pairs to dictionaties

t.getXMLData(identifier[, tmtype])

  • Only call TSDR to get the XML or ZIP file associated with the trademark record indicated; no TSDRMap is provided
  • identifier: a string of digits identifying the number of trademark record to be retrieved.
  • tmtype: a one-character string indicating what type of trademark record is requested:
    • 's': the identifier is a string of eight digits identifying the application serial number of the record to be retrieved. For example, to obtain information on application ser. no 75/181,334, use getTSDRInfo("75181334", "s").
    • 'r': the identifier is a string of seven digits identifying the registration number of the record to be retrieved. For example, to obtain information on registration no. 2,564,831, use getTSDRInfo("2564831", "r").
  • If tmtype is not specified, identifier is the name of a local file that will be read instead of making a call to TSDR. This option is normally used only for development and testing.
  • getXMLData sets the following fields: XMLData, XMLDataIsValid, ErrorCode and ErrorMessage. In addition, if setPTOFormat("ZIP") was specified, it also sets ZipData, as well as ImageThumb and ImageFull if data for those images is present in the ZIP file provided by the USPTO.
  • getXMLData is usually not called directly. Generally, you should use getTSDRInfo instead. You might want to use getXMLData if, for example, you want only the XML data or the trademark image; or if you need to modify the XML data prior to its parsing.

t.getCSVData()

  • Parse the XML previously obtained via getXMLData into key-value pairs expressed as comma-separated values.
  • getCSVData requires that getXMLData have been previously called, that the XMLData field contains valid PTO-formatted XML, and that XMLDataIsValid be set to True
  • getCSVData sets the following fields: CSVData, CSVDataIsValid, ErrorCode and ErrorMessage.
  • getCSVData is usually not called directly.

t.getTSDRData()

  • Transform the CSVData key-value pairs into a TSDRData object.
  • getTSDRData requires that getCSVData have been previously called, that the CSVData field consists of valid CSV-formatted key-value pairs, and that CSVDataIsValid be set to True
  • getTSDRData sets the following fields: TSDRData, TSDRDataIsValid, ErrorCode and ErrorMessage.
  • getTSDRData is usually not called directly.

t.reset()

  • Reset the TSDRReq object t to an initial state. All values previously set, whether by a TDSRReq setXXXX method or by calling TSDR, are cleared. Calling t.reset() is equivalent to the following sequence:
    • t.resetAPIKey()
    • t.resetXSLT()
    • t.resetPTOFormat()
    • t.resetXMLData()

t.setAPIKey(key)

  • key: The 16-character API key obtained from the USPTO
  • Specify the API key TSDR will use to validate the request. Under current USPTO poilicy, calls to TSDR will be rejected unless the API key is set prior to the call.

t.resetAPIKey()

  • Reset the API key, i.e. as is no setAPIKey had ever been called. Under current USPTO policy, subsequent calls to TSDR will be rejected.

t.setPTOFormat(format_name)

  • format_name: a string specifying the format in which TSDR is to return data. Three values are supported:
    • "ST66": request XML formatted according to the ST.66 schema.
    • "ST96": request XML formatted according to the ST.96 schema.
    • "ZIP": request a compressed ZIP file that includes XML (in the format chosen by the USPTO) as well as additional data, such as images of the trademarks,
  • If not set, "ST96" is assumed.
  • Note that the USPTO imposes tighter limits on ZIP file retrievals (4/minute) than straight XML (whether ST.66 or ST.96) retrievals (60/minute). Unless you require access to image data, it is generally better to stay with the default ST.96.

t.resetPTOFormat()

  • Reset the the format in which TSDR is to return data, i.e., to the default ST.96 schema.

t.setXSLT(xslt_template)

  • xslt_template: a string of XSLT used to parse PTO-provided XML into key-pair sets. If not set, Plumage will determine which of the appropriate XSLT templates, provided as part of Plumage, should be used be used.
  • This method may be useful if you need to access some data that Plumage's pre-supplied XSLT templates do not extract from the PTO XML. It enables you to roll-your-own XSLT if the pre-supplied templates are insufficient for your needs. It can also be used to substitute replacement transforms if the PTO changes XML data formats and the supplied transforms no longer work correctly.

t.resetXSLT()

  • Reset the XSLT used to parse the XML returned by TSDR, if previously set. Plumage will use one of the XSLT templates provided as part of Plumage.

t.resetCSVData()

  • Reset the CSV data, if any, previously parsed from XML obtained from TSDR, as well as any data derived from or associated with it. Specifically, resetCSVData does the following:
    • The field CSVData is set to None/null
    • The field CSVDataIsValid is set to False;
    • resetTSDRData() is called to perform further action to clear the TSDRMap derived from the parsed CSV data, and associated data.

t.resetTSDRData()

  • Resets the TSDRData field to an empty TSDRMap object:
    • The fields TSDRSingle and TSDRMulti are set to None/null;
    • The field TSDRMapIsValid is set to False.

t.resetXMLData()

  • Reset the data (XML and/or ZIP file), if any, previously obtained from TSDR, as well as any data derived from or associated with it. Specifically resetXMLData does the following:
    • The fields XMLData, ZipData, ImageFull, ImageThumb, ErrorCode and ErrorCode are set to None/null;
    • The field XMLDataIsValid is set to False;
    • resetCSVData() is called to perform further action to clear any CSV data derived from the XML data.

t.SetIntervalTime(interval)

  • Sets the amount of time that Plumage will ensure passes between TSDR calls.
  • interval is a floating-point number or integer, in seconds
  • If you use setPTOFormat("ZIP") to request zip files, you should also use SetIntervalTime(15) to specify a 15-second interval, because the PTO limits ZIP fetches to 4/minute.
  • Plumage will ensure that the specified amount of time has elapsed between calls to TSDR, to ensure that a sequence of calls stays within PTO-imposed limits. It will minimise the pause to the amount of time needed, or eliminate it entirely. For example, suppose a program need to present trademark image files to a user, which requires setPTOFormat("ZIP"), You use SetIntervalTime(15) to indicate that calls to TSDR should be saparated by 15 seconds. Suppose your program uses getTSDRInfo and then displays the fetched image, and the user takes five seconds to review the image before the program continues with the next TSDR fetch. Plumage will wait only 10 seconds, not the full fifteen seconds; the five seconds that elapsed while the image was reviewed by the user is part of the time elapsed between calls. If the user spent more than fifteen seconds, Plumage will not pause at all, since the full fifteen-second interval would have elapsed without requiring additional pause.

t.GetIntervalTime()

  • Return the current value of the required interval between TSDR calls, in seconds (Python: type float; .NET: type double).

t.ResetIntervalTime()

  • Reset the value of the required interval between TSDR calls tp the default value (1.0 seconds)

TSDRReq data members

The TSDRReq object t includes several data members. The one most often used is t.TSDRData, which contains the data retrieved from TSDR. The following data members exist:

t.CSVData

  • A string containing key/value pairs from TSDR, represented as comma-separated values, derived from XMLData. CSVData The string consists of a series of lines, each consisting of a key and its corresponding value. The key is an alphanumeric string, and the value is a string surrounded by double-quotes. The key and value are separated by a comma, with no spaces on the line, other than within the quote marks. Some examples:
RegistrationNumber,"2564831"
ApplicationNumber,"75181334"
MarkVerbalElementText,"MONTY PYTHON'S FLYING CIRCUS"
ApplicationDate,"1996-10-15"
ApplicantName,"Python (Monty) Pictures Ltd."

In the case of recurring fields, a given set of fields is immediately preceded by the key 'BeginRepeatedField' and a value indicating the type pf field being repeated; and immediately followed by the key 'EndRepeatedField' and the same value as for 'BeginRepeatedField'. For example, each one of a series of MarkEvents will appear as follows:

BeginRepeatedField,"MarkEvent"
RawMarkEventDate,"2002-02-05-05:00"
MarkEventDate,"2002-02-05"
MarkEventDescription,"PUBLISHED FOR OPPOSITION"
MarkEventEntryNumber,"19"
EndRepeatedField,"MarkEvent"

The format of this data is intended to allow it to be loaded into most programs that accept comma-separated-value data, e.g. the Open Document Foundation's LibreOffice or Microsoft Excel. However, its primary use is as an intermediate format transformed from XML, before being converted to a native dictionary. (I would appreciate bug reports if any incompatibilities with CSV-supporting programs are found, however.)

t.CSVDataIsValid

  • A boolean value indicating whether the CSVData field was reliably created.

t.ErrorCode

  • A short string containing a code indicating cause of error, if any; or None/null if no error condition exists. It is intended to be interrogated by the invoking program. This field is discussed in more detail in Errors and exceptions.

t.ErrorMessage

  • A longer string containing a human-readable description of error, if any; or None/null if no error condition exists. It is intended to provide a meaningful description of the error condition. This field is discussed in more detail in Errors and exceptions.

t.ImageFull

  • A binary representation of the full-size image of the mark, if any, in the format provided by TSDR; or None/null if no image data is present
  • The data is represented as type bytes (Python) or byte[] array (.NET) .
  • ImageFull is set only if the TSDR data was obtained with setPTOFormat("zip"). It is the contents of the markImage.jpg member of the retrieved Zip file.
  • Empirical tests indicate that TSDR provides this data in PNG format (despite the zip file member having a ".jpg" suffix).

t.ImageThumb

  • A binary representation of the thumbnail-size image of the mark, if any, in the format provided by TSDR; or None/null if no image data is present
  • The data is represented as type bytes (Python) or byte[] array (.NET) .
  • ImageThumb is set only if the TSDR data was obtained with setPTOFormat("zip"). It is the contents of the markThumbnailImage.jpg member of the retrieved Zip file.
  • Empirical tests indicate that TSDR provides this data in JPEG format.

t.TSDRData

  • a TSDRMap object containing data about the reported trademark registration or application. See TSDRMap .

t.XMLData

  • A string with the XML pertaining to the reported trademark registration or application, as provided by TSDR.

t.XMLDataIsValid

  • A boolean value indicating whether the XMLData field was reliably created.

t.ZipData

  • A binary representation of the Zip file returned by TSDR, if any, in the format provided by TSDR; or None/null if no Zip data is present. This field is set only if the TSDR data was obtained with setPTOFormat("zip").

TSDRMap

The TSDRMap object contains the data associated with the trademark regsitration or application for which TSDR is queried.

TSDRMap data members

TSDRMapIsValid

  • A boolean value indicating whether the TSDRSingle and TSDRMulti fields was reliably created.

TSDRSingle

  • TSDRSingle is a dictionary of attributes that at any one time consists of only one single value for a particular trademark. For example, when an trademark application is filed, the USPTO assigns an application serial number to the application. There is only one application number. The key "ApplicationNumber" has a correponding value, which is a string containing the application serial number of the trademark bout which TSDR is being queried.
  • In Python, TSDRSingle is a dictionary, each key of which is a string, and each corresponding value of which is another string. In .Net, the same format is used; it is formally declared as Dictionary<string, string> .

TSDRMulti

  • TSDRMulti is a dictionary of lists of dictionaries, each of which consists of key-value pairs. TSDRMulti is used where there are (or could be) multiple instances of the same attribute. For example, a trademark may have more than one class identifying the types of goods and services associated with it. This means that there is no one "class" associated with the mark, and the assocaited class(es) cannot necessarily be be represented by a single value.
  • In Python, TSDRMulti is a dictionary, each key of which is a string, and each value of which is a list of dictionaries. Each of those dictionaries represents one of the multiple values that are associated with the mark.
  • In .Net, the same format is used; it is formally declared as Dictionary<string, List<Dictionary<string, string>>>.
  • By convention, every top-level key in TSDRMulti ends with the characters "List". As of Plumage 1.4. TSDRMulti contains the following keys: MarkEventList, ApplicantList, InternationalClassDescriptionList,DomesticClassDescriptionList FirstUseDateList and AssignmentList.

The TSDRMap object, with detail on both TSDRSingle and TSDRMulti, is detailed at TSDRData contents.

For a graphic representation of a typical TSDRSingle and TSDRMulti, see the example in the documentation for TSDR2JSON, an open-source program that uses Plumage to display information about a particular mark in JSON format.