> ## Documentation Index
> Fetch the complete documentation index at: https://docs.compliance.legaltalent.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Watchlists Code Examples

> Code snippets for managing watchlists and monitoring entities

## Overview

Watchlists enable continuous monitoring of entities against sanctions lists. This guide provides ready-to-use code snippets for common watchlist operations.

Key features:

* **Tags**: Organize watchlists and subjects with custom tags for filtering and categorization
* **Session linking**: Connect subjects to onboarding sessions via `session_id`
* **TTL-based expiration**: Subjects automatically expire based on tenant configuration

<CodeGroup>
  ```python theme={null}
  import requests

  BASE_URL = "https://stg.kyc.legaltalent.ai"
  headers = {
      "Authorization": "Bearer YOUR_TOKEN",
      "Content-Type": "application/json"
  }
  ```

  ```javascript theme={null}
  const BASE_URL = 'https://stg.kyc.legaltalent.ai';

  const headers = {
    'Authorization': 'Bearer YOUR_TOKEN',
    'Content-Type': 'application/json'
  };
  ```
</CodeGroup>

## Create Watchlist

<CodeGroup>
  ```python theme={null}
  # Create a basic watchlist with tags
  def create_watchlist(name, lists_to_monitor=None, check_frequency="daily", tags=None):
      url = f"{BASE_URL}/kyc/watchlists"
      payload = {
          "name": name,
          "check_frequency": check_frequency
      }
      
      if lists_to_monitor:
          payload["lists_to_monitor"] = lists_to_monitor
      if tags:
          payload["tags"] = tags
      
      response = requests.post(url, json=payload, headers=headers)
      return response.json()

  # Usage
  watchlist = create_watchlist(
      "High Risk Customers", 
      ["ofac", "un"],
      tags=["compliance", "q4-review"]
  )
  print(f"Created watchlist: {watchlist['data']['watchlist_id']}")

  # Create watchlist with initial subjects (including tags and session_id)
  def create_watchlist_with_subjects(name, subjects, lists_to_monitor=None, tags=None):
      url = f"{BASE_URL}/kyc/watchlists"
      payload = {
          "name": name,
          "subjects": subjects,
          "check_frequency": "daily"
      }
      
      if lists_to_monitor:
          payload["lists_to_monitor"] = lists_to_monitor
      if tags:
          payload["tags"] = tags
      
      response = requests.post(url, json=payload, headers=headers)
      return response.json()

  # Usage with subjects including tags and session_id
  subjects = [
      {
          "full_name": "John Doe",
          "identifier": "12345678",
          "identifier_type": "document",
          "tags": ["vip", "high-risk"],
          "session_id": "sess_abc123"
      },
      {
          "full_name": "Acme Corporation",
          "identifier": "TAX-987654",
          "identifier_type": "tax_id",
          "tags": ["vendor"]
      }
  ]

  watchlist = create_watchlist_with_subjects(
      "Vendor Monitoring", 
      subjects,
      tags=["vendors", "2024"]
  )
  ```

  ```javascript theme={null}
  // Create a basic watchlist with tags
  async function createWatchlist(name, listsToMonitor, checkFrequency = 'daily', tags = []) {
    const url = `${BASE_URL}/kyc/watchlists`;
    const payload = {
      name,
      check_frequency: checkFrequency
    };
    
    if (listsToMonitor) {
      payload.lists_to_monitor = listsToMonitor;
    }
    if (tags.length > 0) {
      payload.tags = tags;
    }
    
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    
    return response.json();
  }

  // Usage
  const watchlist = await createWatchlist(
    'High Risk Customers', 
    ['ofac', 'un'],
    'daily',
    ['compliance', 'q4-review']
  );
  console.log(`Created watchlist: ${watchlist.data.watchlist_id}`);

  // Create watchlist with initial subjects (including tags and session_id)
  async function createWatchlistWithSubjects(name, subjects, listsToMonitor, tags = []) {
    const url = `${BASE_URL}/kyc/watchlists`;
    const payload = {
      name,
      subjects,
      check_frequency: 'daily'
    };
    
    if (listsToMonitor) {
      payload.lists_to_monitor = listsToMonitor;
    }
    if (tags.length > 0) {
      payload.tags = tags;
    }
    
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    
    return response.json();
  }

  // Usage with subjects including tags and session_id
  const subjects = [
    {
      full_name: 'John Doe',
      identifier: '12345678',
      identifier_type: 'document',
      tags: ['vip', 'high-risk'],
      session_id: 'sess_abc123'
    },
    {
      full_name: 'Acme Corporation',
      identifier: 'TAX-987654',
      identifier_type: 'tax_id',
      tags: ['vendor']
    }
  ];

  const watchlist = await createWatchlistWithSubjects(
    'Vendor Monitoring', 
    subjects, 
    null,
    ['vendors', '2024']
  );
  ```
</CodeGroup>

## Create Watchlist with Alerts

<Info>
  Notification channels (webhooks, emails) are configured at the **tenant level**. The `alert_config` only controls **when** to send alerts, not **where**. Contact support to configure your notification channels.
</Info>

<CodeGroup>
  ```python theme={null}
  # Create watchlist with alert configuration
  def create_watchlist_with_alerts(name, on_new_match=True, on_status_change=True):
      url = f"{BASE_URL}/kyc/watchlists"
      payload = {
          "name": name,
          "check_frequency": "daily",
          "lists_to_monitor": ["ofac", "un", "eu"],
          "alert_config": {
              "on_new_match": on_new_match,
              "on_status_change": on_status_change
          }
      }
      
      response = requests.post(url, json=payload, headers=headers)
      return response.json()

  # Usage
  watchlist = create_watchlist_with_alerts(
      "Executive Monitoring",
      on_new_match=True,
      on_status_change=True
  )
  ```

  ```javascript theme={null}
  // Create watchlist with alert configuration
  async function createWatchlistWithAlerts(name, onNewMatch = true, onStatusChange = true) {
    const url = `${BASE_URL}/kyc/watchlists`;
    const payload = {
      name,
      check_frequency: 'daily',
      lists_to_monitor: ['ofac', 'un', 'eu'],
      alert_config: {
        on_new_match: onNewMatch,
        on_status_change: onStatusChange
      }
    };
    
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    
    return response.json();
  }

  // Usage
  const watchlist = await createWatchlistWithAlerts(
    'Executive Monitoring',
    true,
    true
  );
  ```
</CodeGroup>

## List All Watchlists

<CodeGroup>
  ```python theme={null}
  # List all watchlists with optional filtering
  def list_watchlists(active_only=False, tags=None):
      url = f"{BASE_URL}/kyc/watchlists"
      params = {}
      
      if active_only:
          params["active"] = "true"
      if tags:
          params["tags"] = ",".join(tags)
      
      response = requests.get(url, headers=headers, params=params)
      return response.json()

  # Usage - get all watchlists
  watchlists = list_watchlists()
  for wl in watchlists.get("data", {}).get("watchlists", []):
      print(f"{wl['name']} - {wl['watchlist_id']} ({wl['status']}) - Tags: {wl.get('tags', [])}")

  # Get only active watchlists
  active_watchlists = list_watchlists(active_only=True)
  print(f"Active watchlists: {active_watchlists['data']['count']}")

  # Filter by tags
  compliance_watchlists = list_watchlists(tags=["compliance", "high-priority"])
  print(f"Compliance watchlists: {compliance_watchlists['data']['count']}")
  ```

  ```javascript theme={null}
  // List all watchlists with optional filtering
  async function listWatchlists(activeOnly = false, tags = []) {
    const params = new URLSearchParams();
    
    if (activeOnly) {
      params.append('active', 'true');
    }
    if (tags.length > 0) {
      params.append('tags', tags.join(','));
    }
    
    const queryString = params.toString();
    const url = `${BASE_URL}/kyc/watchlists${queryString ? '?' + queryString : ''}`;
    
    const response = await fetch(url, {
      method: 'GET',
      headers
    });
    
    return response.json();
  }

  // Usage - get all watchlists
  const watchlists = await listWatchlists();
  watchlists.data.watchlists.forEach(wl => {
    console.log(`${wl.name} - ${wl.watchlist_id} (${wl.status}) - Tags: ${wl.tags?.join(', ') || 'none'}`);
  });

  // Get only active watchlists
  const activeWatchlists = await listWatchlists(true);
  console.log(`Active watchlists: ${activeWatchlists.data.count}`);

  // Filter by tags
  const complianceWatchlists = await listWatchlists(false, ['compliance', 'high-priority']);
  console.log(`Compliance watchlists: ${complianceWatchlists.data.count}`);
  ```
</CodeGroup>

## Get Watchlist Details

<CodeGroup>
  ```python theme={null}
  # Get watchlist details
  def get_watchlist(watchlist_id):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}"
      response = requests.get(url, headers=headers)
      return response.json()

  # Usage
  watchlist = get_watchlist("550e8400-e29b-41d4-a716-446655440000")
  print(f"Name: {watchlist['data']['name']}")
  print(f"Subjects: {len(watchlist['data']['subjects'])}")
  print(f"Last checked: {watchlist['data'].get('last_checked_at')}")
  ```

  ```javascript theme={null}
  // Get watchlist details
  async function getWatchlist(watchlistId) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}`;
    
    const response = await fetch(url, {
      method: 'GET',
      headers
    });
    
    return response.json();
  }

  // Usage
  const watchlist = await getWatchlist('550e8400-e29b-41d4-a716-446655440000');
  console.log(`Name: ${watchlist.data.name}`);
  console.log(`Subjects: ${watchlist.data.subjects.length}`);
  console.log(`Last checked: ${watchlist.data.last_checked_at}`);
  ```
</CodeGroup>

## Add Subjects

<CodeGroup>
  ```python theme={null}
  # Add single subject with tags and session_id
  def add_subject(watchlist_id, full_name, identifier=None, identifier_type=None, tags=None, session_id=None):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects"
      payload = {"full_name": full_name}
      
      if identifier:
          payload["identifier"] = identifier
      if identifier_type:
          payload["identifier_type"] = identifier_type
      if tags:
          payload["tags"] = tags
      if session_id:
          payload["session_id"] = session_id
      
      response = requests.post(url, json=payload, headers=headers)
      return response.json()

  # Usage
  result = add_subject(
      "550e8400-e29b-41d4-a716-446655440000",
      "Jane Smith",
      identifier="98765432",
      identifier_type="document",
      tags=["priority", "manual-add"],
      session_id="sess_xyz789"
  )

  # Response includes expiration info
  print(f"Subject ID: {result['data']['subject_id']}")
  print(f"Expires at: {result['data']['expires_at']}")
  print(f"Duration: {result['data']['duration_days']} days")

  # Add multiple subjects (batch) with tags
  def add_subjects_batch(watchlist_id, subjects):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects/batch"
      payload = {"subjects": subjects}
      
      response = requests.post(url, json=payload, headers=headers)
      return response.json()

  # Usage with tags and session_id
  subjects = [
      {
          "full_name": "John Doe",
          "identifier": "12345678",
          "identifier_type": "document",
          "tags": ["batch-import", "priority"]
      },
      {
          "full_name": "Acme Corporation",
          "identifier": "TAX-987654",
          "identifier_type": "tax_id",
          "tags": ["vendor", "verified"]
      },
      {
          "full_name": "Crypto Wallet Owner",
          "identifier": "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
          "identifier_type": "wallet",
          "tags": ["crypto"],
          "session_id": "sess_crypto001"
      }
  ]

  result = add_subjects_batch("550e8400-e29b-41d4-a716-446655440000", subjects)
  print(f"Added {result['data']['added_count']} subjects")
  ```

  ```javascript theme={null}
  // Add single subject with tags and session_id
  async function addSubject(watchlistId, fullName, identifier, identifierType, tags = [], sessionId = null) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects`;
    const payload = { full_name: fullName };
    
    if (identifier) {
      payload.identifier = identifier;
    }
    if (identifierType) {
      payload.identifier_type = identifierType;
    }
    if (tags.length > 0) {
      payload.tags = tags;
    }
    if (sessionId) {
      payload.session_id = sessionId;
    }
    
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    
    return response.json();
  }

  // Usage
  const result = await addSubject(
    '550e8400-e29b-41d4-a716-446655440000',
    'Jane Smith',
    '98765432',
    'document',
    ['priority', 'manual-add'],
    'sess_xyz789'
  );

  // Response includes expiration info
  console.log(`Subject ID: ${result.data.subject_id}`);
  console.log(`Expires at: ${result.data.expires_at}`);
  console.log(`Duration: ${result.data.duration_days} days`);

  // Add multiple subjects (batch) with tags
  async function addSubjectsBatch(watchlistId, subjects) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects/batch`;
    const payload = { subjects };
    
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    
    return response.json();
  }

  // Usage with tags and session_id
  const subjects = [
    {
      full_name: 'John Doe',
      identifier: '12345678',
      identifier_type: 'document',
      tags: ['batch-import', 'priority']
    },
    {
      full_name: 'Acme Corporation',
      identifier: 'TAX-987654',
      identifier_type: 'tax_id',
      tags: ['vendor', 'verified']
    },
    {
      full_name: 'Crypto Wallet Owner',
      identifier: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
      identifier_type: 'wallet',
      tags: ['crypto'],
      session_id: 'sess_crypto001'
    }
  ];

  const result = await addSubjectsBatch('550e8400-e29b-41d4-a716-446655440000', subjects);
  console.log(`Added ${result.data.added_count} subjects`);
  ```
</CodeGroup>

## List Subjects

<CodeGroup>
  ```python theme={null}
  # List subjects from a watchlist with optional tag filtering
  def list_subjects(watchlist_id, tags=None):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects"
      params = {}
      
      if tags:
          params["tags"] = ",".join(tags)
      
      response = requests.get(url, headers=headers, params=params)
      return response.json()

  # Usage - get all subjects
  result = list_subjects("550e8400-e29b-41d4-a716-446655440000")
  for subject in result["data"]["subjects"]:
      print(f"{subject['full_name']} - Tags: {subject.get('tags', [])}")

  # Filter by tags
  priority_subjects = list_subjects(
      "550e8400-e29b-41d4-a716-446655440000",
      tags=["priority", "vip"]
  )
  print(f"Found {priority_subjects['data']['count']} priority subjects")
  ```

  ```javascript theme={null}
  // List subjects from a watchlist with optional tag filtering
  async function listSubjects(watchlistId, tags = []) {
    const params = new URLSearchParams();
    
    if (tags.length > 0) {
      params.append('tags', tags.join(','));
    }
    
    const queryString = params.toString();
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects${queryString ? '?' + queryString : ''}`;
    
    const response = await fetch(url, {
      method: 'GET',
      headers
    });
    
    return response.json();
  }

  // Usage - get all subjects
  const result = await listSubjects('550e8400-e29b-41d4-a716-446655440000');
  result.data.subjects.forEach(subject => {
    console.log(`${subject.full_name} - Tags: ${subject.tags?.join(', ') || 'none'}`);
  });

  // Filter by tags
  const prioritySubjects = await listSubjects(
    '550e8400-e29b-41d4-a716-446655440000',
    ['priority', 'vip']
  );
  console.log(`Found ${prioritySubjects.data.count} priority subjects`);
  ```
</CodeGroup>

## Update Subject Tags

<CodeGroup>
  ```python theme={null}
  # Update tags for a subject
  def update_subject_tags(watchlist_id, subject_id, tags):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects/{subject_id}"
      payload = {"tags": tags}
      
      response = requests.patch(url, json=payload, headers=headers)
      return response.json()

  # Usage - replace subject tags
  result = update_subject_tags(
      "550e8400-e29b-41d4-a716-446655440000",
      "660e8400-e29b-41d4-a716-446655440001",
      ["reviewed", "cleared", "low-risk"]
  )
  print(f"Updated tags: {result['data']['tags']}")
  ```

  ```javascript theme={null}
  // Update tags for a subject
  async function updateSubjectTags(watchlistId, subjectId, tags) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects/${subjectId}`;
    const payload = { tags };
    
    const response = await fetch(url, {
      method: 'PATCH',
      headers,
      body: JSON.stringify(payload)
    });
    
    return response.json();
  }

  // Usage - replace subject tags
  const result = await updateSubjectTags(
    '550e8400-e29b-41d4-a716-446655440000',
    '660e8400-e29b-41d4-a716-446655440001',
    ['reviewed', 'cleared', 'low-risk']
  );
  console.log(`Updated tags: ${result.data.tags.join(', ')}`);
  ```
</CodeGroup>

## Remove Subject

<CodeGroup>
  ```python theme={null}
  # Remove subject from watchlist
  def remove_subject(watchlist_id, subject_id):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects/{subject_id}"
      response = requests.delete(url, headers=headers)
      return response.json()

  # Usage
  result = remove_subject(
      "550e8400-e29b-41d4-a716-446655440000",
      "660e8400-e29b-41d4-a716-446655440001"
  )
  ```

  ```javascript theme={null}
  // Remove subject from watchlist
  async function removeSubject(watchlistId, subjectId) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects/${subjectId}`;
    
    const response = await fetch(url, {
      method: 'DELETE',
      headers
    });
    
    return response.json();
  }

  // Usage
  const result = await removeSubject(
    '550e8400-e29b-41d4-a716-446655440000',
    '660e8400-e29b-41d4-a716-446655440001'
  );
  ```
</CodeGroup>

## Update Watchlist

<CodeGroup>
  ```python theme={null}
  # Update watchlist configuration
  def update_watchlist(watchlist_id, name=None, check_frequency=None, 
                       lists_to_monitor=None, status=None, alert_config=None, tags=None):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}"
      payload = {}
      
      if name:
          payload["name"] = name
      if check_frequency:
          payload["check_frequency"] = check_frequency
      if lists_to_monitor:
          payload["lists_to_monitor"] = lists_to_monitor
      if status:
          payload["status"] = status
      if alert_config:
          payload["alert_config"] = alert_config
      if tags is not None:
          payload["tags"] = tags
      
      response = requests.patch(url, json=payload, headers=headers)  # Use PATCH, not PUT
      return response.json()

  # Usage examples
  # Update name
  update_watchlist("550e8400-e29b-41d4-a716-446655440000", name="Updated Name")

  # Change frequency
  update_watchlist("550e8400-e29b-41d4-a716-446655440000", check_frequency="weekly")

  # Pause watchlist
  update_watchlist("550e8400-e29b-41d4-a716-446655440000", status="paused")

  # Resume watchlist
  update_watchlist("550e8400-e29b-41d4-a716-446655440000", status="active")

  # Update tags
  update_watchlist("550e8400-e29b-41d4-a716-446655440000", tags=["reviewed", "priority"])

  # Update alert config (only when to alert, not where)
  update_watchlist(
      "550e8400-e29b-41d4-a716-446655440000",
      alert_config={
          "on_new_match": True,
          "on_status_change": True
      }
  )
  ```

  ```javascript theme={null}
  // Update watchlist configuration
  async function updateWatchlist(watchlistId, updates) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}`;
    
    const response = await fetch(url, {
      method: 'PATCH',  // Use PATCH, not PUT
      headers,
      body: JSON.stringify(updates)
    });
    
    return response.json();
  }

  // Usage examples
  // Update name
  await updateWatchlist('550e8400-e29b-41d4-a716-446655440000', {
    name: 'Updated Name'
  });

  // Change frequency
  await updateWatchlist('550e8400-e29b-41d4-a716-446655440000', {
    check_frequency: 'weekly'
  });

  // Pause watchlist
  await updateWatchlist('550e8400-e29b-41d4-a716-446655440000', {
    status: 'paused'
  });

  // Resume watchlist
  await updateWatchlist('550e8400-e29b-41d4-a716-446655440000', {
    status: 'active'
  });

  // Update tags
  await updateWatchlist('550e8400-e29b-41d4-a716-446655440000', {
    tags: ['reviewed', 'priority']
  });

  // Update alert config (only when to alert, not where)
  await updateWatchlist('550e8400-e29b-41d4-a716-446655440000', {
    alert_config: {
      on_new_match: true,
      on_status_change: true
    }
  });
  ```
</CodeGroup>

## Trigger Monitoring

Run an immediate screening check on all subjects in a watchlist without waiting for the scheduled check.

<CodeGroup>
  ```python theme={null}
  # Trigger monitoring immediately
  def trigger_monitoring(watchlist_id):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/monitor"
      response = requests.post(url, headers=headers)
      return response.json()

  # Usage
  result = trigger_monitoring("550e8400-e29b-41d4-a716-446655440000")

  if result["status"] == "success":
      data = result["data"]
      print(f"Checked {data['subjects_checked']} subjects")
      print(f"Found {data['new_matches_count']} new matches")
      
      if data["has_changes"]:
          print("⚠️ Match status changed since last check!")
  ```

  ```javascript theme={null}
  // Trigger monitoring immediately
  async function triggerMonitoring(watchlistId) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/monitor`;
    
    const response = await fetch(url, {
      method: 'POST',
      headers
    });
    
    return response.json();
  }

  // Usage
  const result = await triggerMonitoring('550e8400-e29b-41d4-a716-446655440000');

  if (result.status === 'success') {
    const { subjects_checked, new_matches_count, has_changes } = result.data;
    console.log(`Checked ${subjects_checked} subjects`);
    console.log(`Found ${new_matches_count} new matches`);
    
    if (has_changes) {
      console.log('⚠️ Match status changed since last check!');
    }
  }
  ```
</CodeGroup>

## Delete Watchlist

<CodeGroup>
  ```python theme={null}
  # Delete watchlist
  def delete_watchlist(watchlist_id):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}"
      response = requests.delete(url, headers=headers)
      return response.json()

  # Usage
  result = delete_watchlist("550e8400-e29b-41d4-a716-446655440000")
  ```

  ```javascript theme={null}
  // Delete watchlist
  async function deleteWatchlist(watchlistId) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}`;
    
    const response = await fetch(url, {
      method: 'DELETE',
      headers
    });
    
    return response.json();
  }

  // Usage
  const result = await deleteWatchlist('550e8400-e29b-41d4-a716-446655440000');
  ```
</CodeGroup>

## Common Workflows

### Complete Watchlist Management

<CodeGroup>
  ```python theme={null}
  class WatchlistManager:
      def __init__(self, base_url, token):
          self.base_url = base_url
          self.headers = {
              "Authorization": f"Bearer {token}",
              "Content-Type": "application/json"
          }
      
      def create(self, name, lists_to_monitor=None, tags=None):
          url = f"{self.base_url}/kyc/watchlists"
          payload = {"name": name, "check_frequency": "daily"}
          if lists_to_monitor:
              payload["lists_to_monitor"] = lists_to_monitor
          if tags:
              payload["tags"] = tags
          
          response = requests.post(url, json=payload, headers=self.headers)
          return response.json()
      
      def get(self, watchlist_id):
          url = f"{self.base_url}/kyc/watchlists/{watchlist_id}"
          response = requests.get(url, headers=self.headers)
          return response.json()
      
      def add_subject(self, watchlist_id, full_name, identifier=None, identifier_type=None, tags=None, session_id=None):
          url = f"{self.base_url}/kyc/watchlists/{watchlist_id}/subjects"
          payload = {"full_name": full_name}
          if identifier:
              payload["identifier"] = identifier
          if identifier_type:
              payload["identifier_type"] = identifier_type
          if tags:
              payload["tags"] = tags
          if session_id:
              payload["session_id"] = session_id
          
          response = requests.post(url, json=payload, headers=self.headers)
          return response.json()
      
      def list_subjects(self, watchlist_id, tags=None):
          url = f"{self.base_url}/kyc/watchlists/{watchlist_id}/subjects"
          params = {}
          if tags:
              params["tags"] = ",".join(tags)
          response = requests.get(url, headers=self.headers, params=params)
          return response.json()
      
      def update_subject_tags(self, watchlist_id, subject_id, tags):
          url = f"{self.base_url}/kyc/watchlists/{watchlist_id}/subjects/{subject_id}"
          payload = {"tags": tags}
          response = requests.patch(url, json=payload, headers=self.headers)
          return response.json()
      
      def list_all(self, tags=None):
          url = f"{self.base_url}/kyc/watchlists"
          params = {}
          if tags:
              params["tags"] = ",".join(tags)
          response = requests.get(url, headers=self.headers, params=params)
          return response.json()
      
      def delete(self, watchlist_id):
          url = f"{self.base_url}/kyc/watchlists/{watchlist_id}"
          response = requests.delete(url, headers=self.headers)
          return response.json()

  # Usage
  manager = WatchlistManager(BASE_URL, "YOUR_TOKEN")

  # Create watchlist with tags
  watchlist = manager.create("Customer Monitoring", ["ofac", "un"], tags=["compliance"])
  watchlist_id = watchlist["data"]["watchlist_id"]

  # Add subjects with tags and session_id
  manager.add_subject(watchlist_id, "John Doe", "12345678", "document", tags=["vip"], session_id="sess_001")
  manager.add_subject(watchlist_id, "Jane Smith", "87654321", "document", tags=["priority"])

  # Get details
  details = manager.get(watchlist_id)
  print(f"Monitoring {len(details['data']['subjects'])} subjects")

  # List subjects filtered by tags
  vip_subjects = manager.list_subjects(watchlist_id, tags=["vip"])
  print(f"VIP subjects: {vip_subjects['data']['count']}")
  ```

  ```javascript theme={null}
  class WatchlistManager {
    constructor(baseUrl, token) {
      this.baseUrl = baseUrl;
      this.headers = {
        'Authorization': `Bearer ${token}`,
        'Content-Type': 'application/json'
      };
    }
    
    async create(name, listsToMonitor, tags = []) {
      const url = `${this.baseUrl}/kyc/watchlists`;
      const payload = { name, check_frequency: 'daily' };
      if (listsToMonitor) {
        payload.lists_to_monitor = listsToMonitor;
      }
      if (tags.length > 0) {
        payload.tags = tags;
      }
      
      const response = await fetch(url, {
        method: 'POST',
        headers: this.headers,
        body: JSON.stringify(payload)
      });
      
      return response.json();
    }
    
    async get(watchlistId) {
      const url = `${this.baseUrl}/kyc/watchlists/${watchlistId}`;
      const response = await fetch(url, {
        method: 'GET',
        headers: this.headers
      });
      
      return response.json();
    }
    
    async addSubject(watchlistId, fullName, identifier, identifierType, tags = [], sessionId = null) {
      const url = `${this.baseUrl}/kyc/watchlists/${watchlistId}/subjects`;
      const payload = { full_name: fullName };
      if (identifier) {
        payload.identifier = identifier;
      }
      if (identifierType) {
        payload.identifier_type = identifierType;
      }
      if (tags.length > 0) {
        payload.tags = tags;
      }
      if (sessionId) {
        payload.session_id = sessionId;
      }
      
      const response = await fetch(url, {
        method: 'POST',
        headers: this.headers,
        body: JSON.stringify(payload)
      });
      
      return response.json();
    }
    
    async listSubjects(watchlistId, tags = []) {
      const params = new URLSearchParams();
      if (tags.length > 0) {
        params.append('tags', tags.join(','));
      }
      const queryString = params.toString();
      const url = `${this.baseUrl}/kyc/watchlists/${watchlistId}/subjects${queryString ? '?' + queryString : ''}`;
      
      const response = await fetch(url, {
        method: 'GET',
        headers: this.headers
      });
      
      return response.json();
    }
    
    async updateSubjectTags(watchlistId, subjectId, tags) {
      const url = `${this.baseUrl}/kyc/watchlists/${watchlistId}/subjects/${subjectId}`;
      const payload = { tags };
      
      const response = await fetch(url, {
        method: 'PATCH',
        headers: this.headers,
        body: JSON.stringify(payload)
      });
      
      return response.json();
    }
    
    async listAll(tags = []) {
      const params = new URLSearchParams();
      if (tags.length > 0) {
        params.append('tags', tags.join(','));
      }
      const queryString = params.toString();
      const url = `${this.baseUrl}/kyc/watchlists${queryString ? '?' + queryString : ''}`;
      
      const response = await fetch(url, {
        method: 'GET',
        headers: this.headers
      });
      
      return response.json();
    }
    
    async delete(watchlistId) {
      const url = `${this.baseUrl}/kyc/watchlists/${watchlistId}`;
      const response = await fetch(url, {
        method: 'DELETE',
        headers: this.headers
      });
      
      return response.json();
    }
  }

  // Usage
  const manager = new WatchlistManager(BASE_URL, 'YOUR_TOKEN');

  // Create watchlist with tags
  const watchlist = await manager.create('Customer Monitoring', ['ofac', 'un'], ['compliance']);
  const watchlistId = watchlist.data.watchlist_id;

  // Add subjects with tags and session_id
  await manager.addSubject(watchlistId, 'John Doe', '12345678', 'document', ['vip'], 'sess_001');
  await manager.addSubject(watchlistId, 'Jane Smith', '87654321', 'document', ['priority']);

  // Get details
  const details = await manager.get(watchlistId);
  console.log(`Monitoring ${details.data.subjects.length} subjects`);

  // List subjects filtered by tags
  const vipSubjects = await manager.listSubjects(watchlistId, ['vip']);
  console.log(`VIP subjects: ${vipSubjects.data.count}`);
  ```
</CodeGroup>

### Bulk Import Subjects

<CodeGroup>
  ```python theme={null}
  # Import multiple subjects from a list with tags
  def import_subjects_to_watchlist(watchlist_id, subjects_list):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects/batch"
      
      # Process in batches of 50
      batch_size = 50
      results = []
      
      for i in range(0, len(subjects_list), batch_size):
          batch = subjects_list[i:i + batch_size]
          payload = {"subjects": batch}
          
          response = requests.post(url, json=payload, headers=headers)
          results.append(response.json())
      
      return results

  # Usage with tags
  subjects_to_import = [
      {
          "full_name": f"Person {i}", 
          "identifier": f"ID{i}", 
          "identifier_type": "document",
          "tags": ["bulk-import", "batch-1"]
      }
      for i in range(1, 101)
  ]

  results = import_subjects_to_watchlist("550e8400-e29b-41d4-a716-446655440000", subjects_to_import)

  # Check results
  for batch_result in results:
      if batch_result["status"] == "success":
          print(f"Added {batch_result['data']['added_count']} subjects")
  ```

  ```javascript theme={null}
  // Import multiple subjects from a list with tags
  async function importSubjectsToWatchlist(watchlistId, subjectsList) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects/batch`;
    
    // Process in batches of 50
    const batchSize = 50;
    const results = [];
    
    for (let i = 0; i < subjectsList.length; i += batchSize) {
      const batch = subjectsList.slice(i, i + batchSize);
      const payload = { subjects: batch };
      
      const response = await fetch(url, {
        method: 'POST',
        headers,
        body: JSON.stringify(payload)
      });
      
      results.push(await response.json());
    }
    
    return results;
  }

  // Usage with tags
  const subjectsToImport = Array.from({ length: 100 }, (_, i) => ({
    full_name: `Person ${i + 1}`,
    identifier: `ID${i + 1}`,
    identifier_type: 'document',
    tags: ['bulk-import', 'batch-1']
  }));

  const results = await importSubjectsToWatchlist('550e8400-e29b-41d4-a716-446655440000', subjectsToImport);

  // Check results
  for (const batchResult of results) {
    if (batchResult.status === 'success') {
      console.log(`Added ${batchResult.data.added_count} subjects`);
    }
  }
  ```
</CodeGroup>

## Error Handling

<CodeGroup>
  ```python theme={null}
  import requests
  from requests.exceptions import RequestException

  def safe_watchlist_operation(operation_func, *args, **kwargs):
      try:
          result = operation_func(*args, **kwargs)
          
          if "error" in result:
              print(f"API Error: {result['error']}")
              return None
          
          return result
          
      except RequestException as e:
          print(f"Request failed: {e}")
          return None
      except Exception as e:
          print(f"Unexpected error: {e}")
          return None

  # Usage
  def create_watchlist_safe(name):
      def _create():
          url = f"{BASE_URL}/kyc/watchlists"
          response = requests.post(url, json={"name": name}, headers=headers, timeout=30)
          response.raise_for_status()
          return response.json()
      
      return safe_watchlist_operation(_create)
  ```

  ```javascript theme={null}
  async function safeWatchlistOperation(operation) {
    try {
      const result = await operation();
      
      if (result.error) {
        console.error('API Error:', result.error);
        return null;
      }
      
      return result;
      
    } catch (error) {
      console.error('Request failed:', error);
      return null;
    }
  }

  // Usage
  async function createWatchlistSafe(name) {
    return safeWatchlistOperation(async () => {
      const url = `${BASE_URL}/kyc/watchlists`;
      const response = await fetch(url, {
        method: 'POST',
        headers,
        body: JSON.stringify({ name }),
        signal: AbortSignal.timeout(30000)
      });
      
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      
      return response.json();
    });
  }
  ```
</CodeGroup>

## Handling Seat Limits

When adding subjects, the API validates available seats. Handle 402 errors gracefully:

<CodeGroup>
  ```python theme={null}
  def add_subject_with_seat_check(watchlist_id, full_name, identifier=None, tags=None):
      url = f"{BASE_URL}/kyc/watchlists/{watchlist_id}/subjects"
      payload = {"full_name": full_name}
      if identifier:
          payload["identifier"] = identifier
      if tags:
          payload["tags"] = tags
      
      response = requests.post(url, json=payload, headers=headers)
      result = response.json()
      
      if response.status_code == 402:
          print("⚠️ No seats available! Please purchase more seats.")
          return None
      
      if result["status"] == "success":
          data = result["data"]
          # Subject expires at this timestamp (Unix timestamp)
          expires_at = data["expires_at"]
          duration_days = data["duration_days"]
          subject_id = data["subject_id"]
          print(f"Subject {subject_id} added. Expires in {duration_days} days (at {expires_at})")
      
      return result
  ```

  ```javascript theme={null}
  async function addSubjectWithSeatCheck(watchlistId, fullName, identifier, tags = []) {
    const url = `${BASE_URL}/kyc/watchlists/${watchlistId}/subjects`;
    const payload = { full_name: fullName };
    if (identifier) {
      payload.identifier = identifier;
    }
    if (tags.length > 0) {
      payload.tags = tags;
    }
    
    const response = await fetch(url, {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });
    
    if (response.status === 402) {
      console.log('⚠️ No seats available! Please purchase more seats.');
      return null;
    }
    
    const result = await response.json();
    
    if (result.status === 'success') {
      const { subject_id, expires_at, duration_days } = result.data;
      // Subject expires at this timestamp (Unix timestamp)
      console.log(`Subject ${subject_id} added. Expires in ${duration_days} days (at ${expires_at})`);
    }
    
    return result;
  }
  ```
</CodeGroup>

## Related References

* [Watchlists API Reference](/api-reference/watchlists) - Full API documentation
* [Create Watchlist](/api-reference/watchlists/create) - Create watchlist endpoint
* [Add Subjects](/api-reference/watchlists/add-subjects) - Add subjects to watchlist
* [Trigger Monitoring](/api-reference/watchlists/trigger-monitoring) - On-demand screening
* [List Check API](/api-reference/list-check) - One-time checks
* [Validate Person or Company](/validate-person-entity) - Individual entity validation guide
