Your guide to the Moov Watchman API

The Moov Watchman project provides search functionality over U.S. trade sanctions lists, including individuals, groups, and companies legally forbidden to transact with. While the project’s primary API documentation contains plenty of technical details and examples, the purpose of this guide is to serve as a launching point for new users. We’ll cover how to perform a few types of Watchman searches and how to update an entry’s status using our API service.


Entities on trade sanctions lists may pose a threat to national security and must be avoided when doing business. Failure to comply with trade restrictions typically results in significant fines imposed by the federal government (see recent incidents with Apple and Berkshire Hathaway). The Moov Watchman project only covers data maintained by the U.S. government, but we plan to include trade sanction lists for other countries in the future.

Moov Watchman offers search functions over the following data:

The general search endpoint covers all the lists noted above, and several operations under the ofac endpoint search the SDN list exclusively. The SDN list contains a few different data files, including base entries, alternative names, addresses, and comments. Our API parses this information and outputs search results in JSON format. Since SDN entries are frequently updated, we also support webhooks to track their statuses.

Although some individual lists offer their own search UI, our API makes searching more efficient by parsing multiple data sources and returning results in a more usable format. We also provide an in-browser Watchman tool with an intuitive UI ideal for quick searches.

Initial setup

The easiest way to get started with the Watchman API is to install Docker on your system and run the latest Watchman image in your terminal with docker run -p 8084:8084 -p 9094:9094 moov/watchman:latest. This step automatically pulls the latest image and runs the API on port 8084 with Prometheus metrics on port 9094.

To ensure the service is active, you can ping it with curl localhost:8084/ping. If it’s up and running, you’ll receive an HTTP 200 status with PONG as the response body. Otherwise, you’ll see something like Failed to connect to localhost port 8084: Connection refused.

The search endpoint lets you perform a general search across all lists supported by Watchman. Several search parameters are available, including name, address, and alternative name. You can also apply sdnType or program filters to narrow down SDN results. For example, sdnType=vessel will only return SDNs that are vessels. A full list of valid parameters is available in our Watchman API documentation.

Behind the scenes, the API uses a variety of search algorithms from smetrics. Search values are case insensitive and results are ordered by match percentage. Please note if you choose to set a limit on results, it will apply individually to all lists being searched. Let’s take a look at a few examples below.

To perform a search across all lists for John and return one result from each list:

curl "localhost:8084/search?q=John&limit=1"

To perform an address search for 5250 Ferrier Street and return one result:

curl "localhost:8084/search?address=5250+Ferrier+Street&limit=1"

To perform a name search for Midco Finance and restrict SDN results to only companies (entities):

curl "localhost:8084/search?name=Midco+Finance&sdnType=entity"

Notice & separates search parameters and + represents a space within parameter values in the search query.

Obtain a list of possible values for an SDN property

As mentioned in the section above, you can filter a general search by SDN type or program. Since the possible values for these properties may change over time, we offer an endpoint that will return all values that currently exist. Simply specify a key (sdnType or ofacProgram) and you’ll receive a list of possible values for that property. For example, curl localhost:8084/ui/values/sdnType returns ["aircraft","entity","individual","vessel"].

Searching SDNs by ID

We offer a few different ways to obtain SDN information. One method is to search by company or customer ID, as each SDN entry has a unique ID number. This will return all information surrounding a given entry, including any associated alternative names, addresses, and comments.

To obtain details about a company, use:

curl "localhost:8084/ofac/companies/<INSERT-ID>"

To obtain details about a customer, use:

curl "localhost:8084/ofac/customers/<INSERT-ID>"

The response body will look like this:

{"id":"2683","sdn":{"entityID":"2683","sdnName":"JABRIL, Ahmad","sdnType":"individual","program":["SDGT"],"title":"Secretary General of POPULAR FRONT FOR THE LIBERATION OF PALESTINE - GENERAL COMMAND","callSign":"","vesselType":"","tonnage":"","grossRegisteredTonnage":"","vesselFlag":"","vesselOwner":"","remarks":"DOB 1938; POB Ramleh, Israel; Secretary General of POPULAR FRONT FOR THE LIBERATION OF PALESTINE - GENERAL COMMAND."},"addresses":[{"entityID":"2683","addressID":"1841","address":"","cityStateProvincePostalCode":"","country":"","addressRemarks":""}],"alts":[{"entityID":"2683","alternateID":"1823","alternateType":"aka","alternateName":"JIBRIL, Ahmad","alternateRemarks":""}],"comments":null,"status":null}

If you accidentally search for a customer using /company or vice versa, you will get a null response. Similarly, if you submit an ID that doesn’t exist on the SDN list as either a company or customer, you will get a response that looks like {"error": "Company/Customer <ID> not found"}.

We have a few other endpoints that narrow down the amount of information returned for a given SDN lookup. You can use the same entry IDs mentioned previously, and these endpoints do not differentiate between companies and customers.

To retrieve only general info for an SDN, use:

curl "localhost:8084/ofac/sdn/<INSERT-ID>

To retrieve only associated addresses for an SDN, use:

curl "localhost:8084/ofac/sdn/<INSERT-ID>/addresses"

To retrieve only associated alternative names for an SDN, use:

curl "localhost:8084/ofac/sdn/<INSERT-ID>/alts"

Lastly, we offer an admin endpoint that provides an SDN’s general information alongside its exact text stored in our index used for string ranking. For this function, use:

curl "localhost:9094/debug/sdn/<INSERT-ID>"

Updating SDNs

You may have noticed the status field associated with each SDN entry. This field is empty by default, but can be set with the API. It allows for more customization and includes an author ID, note, block status, and timestamp. To update an entry’s status, provide both a block status (unsafe or exception) and free form note in the request body. The complete cURL command would look like:

curl -X PUT -d '{"status": "exception", "notes":"random note"}' -H "X-User-ID:12345" localhost:8084/ofac/customers/<INSERT-ID>

Once the changes go through, the SDN entry’s status will be updated to:

{"userID": 12345", "note":"random note", "block": "exception", "createdAt": "2021-05-25T20:15:44"}

If you’d like to update the status of a company instead, take the previous cURL command and change /customers to /company.


We hope this walkthrough helps you get started with Watchman and serves as a quick refresher for current users. The API is only a fraction of the entire project, so we encourage you to visit Watchman on GitHub too! If you have any questions or suggestions for Watchman, please contact the Moov team on Slack (#watchman channel) or submit an issue.