Watchtower by Lighthouse
API Reference
https://watchtowerkyc.com/api/v1

Getting Started

The Watchtower API lets your own software do what your staff do on the site. It can add and change parties, screen them, read the results and download certificates and reports.

The API comes with the Firm and Institution plans.

An administrator at your firm makes a key on the Account page. We show the key once, so copy it then. Your firm may hold five keys at a time, and an administrator can cancel a key at any moment.

Send the key with every call, in the Authorization header. Every call is made over HTTPS and answers in JSON.

A First Call
curl https://watchtowerkyc.com/api/v1/usage \
  -H "Authorization: Bearer wt_test_your_key"

Test Keys

A test key works on invented names. Use one to build and prove your integration before you send a client's name.

A test key answers from a book of five invented parties, one for each answer the service gives. Their identifiers begin test_pty_ and their references run from TEST-0001 to TEST-0005.

A party you add with a test key is checked and screened against an invented list and returned to you. We do not keep it, so you cannot fetch it afterwards.

Viktor Samplov Testovich, born 1961-04-02, returns a match. Viktor Samplov with no date of birth returns a review. Maria Example Fernandez, born in 1970, returns an office-holder match. Any other name returns clear.

Certificates and reports asked for with a test key are the samples from our website, marked SAMPLE on every page. Every answer to a test key carries test: true.

Parties

A party is a person or an entity you screen. The fields and the checks are those of the Add a Party form.

Lists come 200 to a page. When next_cursor is not null, send it back as cursor to get the next page. You may ask for a smaller page with limit.

The limit on parties in your plan applies to the API as it does to the site.

FieldMeaning
kindPerson or Entity. Required.
nameThe full name, of two words or more. Required.
former_namesA list of former names and aliases, ten at most. Each is screened as well.
date_of_birthWritten YYYY-MM-DD. Persons only.
nationalityFree text, 80 characters at most.
referenceYour own file or client reference, 80 characters at most.
roleThe party's role or relationship, 120 characters at most.
POST /partiesAdd one party. We screen it at once and return it with its result.
POST /parties/batchAdd up to 1,000 parties, sent as { "parties": [ ... ] }. We check every party first. If any has an error we add none and tell you which.
GET /partiesList your parties in the order they were added. Add ?reference= to find the parties filed under one of your references.
GET /parties/{id}One party with its latest result.
PATCH /parties/{id}Change a party. Send only the fields you are changing. A change to the name, date of birth or nationality screens the party again and reopens earlier decisions about it.
POST /parties/{id}/stopStop monitoring a party. We keep its history.
POST /parties/{id}/resumeResume monitoring a party.
Adding a Party
curl https://watchtowerkyc.com/api/v1/parties \
  -H "Authorization: Bearer wt_test_your_key" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7f1c2a9e-0001" \
  -d '{"kind":"Person","name":"Jane Sample Doe","date_of_birth":"1985-03-14","reference":"C-1042"}'

Screening

We screen a party when you add it and each time your schedule falls due. You can also screen on demand.

A run of your whole book answers when the run has finished. One run may be under way for your firm at a time.

POST /parties/{id}/screenScreen one party again now.
POST /screeningsScreen all your monitored parties now.
GET /screeningsYour runs, newest first, with the totals of each.
GET /screenings/{id}One run: whether it has finished, its totals and the lists it ran against.
GET /screenings/{id}/resultsThe results of a run. Add ?flagged=true to keep only review and match.
GET /listsThe sanctions lists and rosters we screen against, with the date each was last updated.

Results

A result gives the sanctions outcome and the office-holder outcome separately. Each is clear, review, match or not_completed.

Clear means we found no entry under that name. Review means a name matched and a person at your firm must decide. Match means the name and the year of birth both matched.

office_holders is null when no office-holder screen was made. That is the case for every entity.

Each match names the list, the name on the list, the list's own reference, whether the year of birth agrees and whether the match was reached through a difference in spelling.

Your compliance officer records the decision on a match on the site. The result then carries that decision, with the reviewer and the date.

GET /results/{id}One result in full.
GET /parties/{id}/resultsEvery result for one party, newest first.
GET /reviewThe results waiting for a decision.
A Result
{
  "id": "test_res_review",
  "party_id": "test_pty_review",
  "screening_id": "test_run_1",
  "screened_at": "2026-01-01T12:00:00.000Z",
  "screened": { "name": "Viktor Samplov", "kind": "Person", "date_of_birth": null },
  "sanctions": {
    "outcome": "review",
    "matches": [
      {
        "list": "TEST-LIST",
        "name": "Viktor Samplov Testovich",
        "reference": "T-001",
        "date_of_birth": "1961-04-02",
        "birth_year_agrees": false,
        "spelling_variant": false,
        "ruled_out": false
      }
    ]
  },
  "office_holders": { "outcome": "clear", "matches": [] },
  "decision": null,
  "test": true
}

Certificates and Reports

These calls return a PDF. They are the documents the site produces, locked and digitally signed in the same way.

GET /results/{id}/certificateThe Screening Certificate for one result.
GET /screenings/{id}/reportThe Screening Report for one run.

Your Plan

GET /usageYour plan, its limit on parties and the number you are monitoring.

Sending a Call Twice

A network fault can leave you unsure whether a call arrived. When you add a party or a batch, send an Idempotency-Key header with a value of your own, such as a UUID.

If the same call arrives again within a day with the same key, we return the first answer and add nothing.

Pace

Your firm may make 600 calls a minute across all its keys. A call over that pace is refused with status 429, and the Retry-After header says how many seconds to wait.

Errors

A call that cannot be completed answers with an HTTP status of 400 or above and a body of this form: { "error": { "code": "...", "message": "..." } }. The code is fixed and your software can act on it. The message is for a person.

CodeStatusMessage
no_key401This call needs an API key. Send it in the Authorization header as a Bearer token.
bad_key401This API key is not valid. It may have been cancelled.
no_api_on_plan403The API comes with the Firm and Institution plans.
subscription_ended403This subscription has ended, and its API keys no longer work. Your records can be read and downloaded on the site until they are deleted.
too_many_calls429Too many calls. The limit is 600 a minute. Try again in a moment.
bad_json400The request body could not be read as JSON.
invalid422The request has errors.
batch_too_large422A batch holds at most 1,000 parties.
batch_empty422The batch holds no parties.
over_limit409The plan’s limit on parties has been reached.
key_reused409This Idempotency-Key was used for a different request.
party_not_found404That party does not exist.
result_not_found404That result does not exist.
screening_not_found404That screening does not exist.
not_monitored409This party is not being monitored. Resume monitoring to screen it.
nothing_to_screen409There are no monitored parties to screen.
screening_under_way409A screening is already under way. Try again in a few minutes.
lists_not_loaded503The sanctions lists are not loaded yet. Try again in a few minutes.
no_certificate404This result has no certificate, because the screening was not completed.
no_report404This screening has no report, because it has not finished.
bad_limit400The limit must be a number from 1 to 200.

Changes

The address carries the version, v1. We may add calls and fields to v1. We will not rename or remove a field, or change what a call does, within v1.

Questions about the API go to support@watchtowerkyc.com, or to a ticket on the Support page.