Skip to main content
POST
/
kyc
/
adverse-media
curl -X POST https://stg.kyc.legaltalent.ai/kyc/adverse-media \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "John Doe"
    }'
{
  "final_risk_score": 75,
  "decision": "HIGH_RISK",
  "summary": "Multiple adverse media findings identified including fraud allegations and regulatory violations.",
  "sources": [
    {
      "id": 1,
      "title": "Tech Executive Charged with Fraud",
      "url": "https://example.com/news/article1",
      "summary": "John Doe, CEO of Tech Corp, faces fraud charges related to investor funds..."
    },
    {
      "id": 3,
      "title": "SEC Investigation into Tech Corp",
      "url": "https://example.com/news/article2",
      "summary": "SEC investigating Tech Corp for securities violations involving executive..."
    }
  ],
  "entity_name": "John Doe",
  "entity_type": "person",
  "country": "US",
  "age": 45,
  "analysis_timestamp": "2024-11-22T10:30:00Z",
  "processing_time_ms": 6000
}
Perform adverse media analysis on entities to identify negative news, sanctions, criminal records, and other risk factors beyond traditional watchlist checks. Supports analysis of persons, companies, and websites/domains.

Endpoint

POST /kyc/adverse-media

Authentication

Requires kyc:create permission. Include your Bearer token in the Authorization header.

Description

The adverse media check uses AI-powered analysis to search and evaluate publicly available information about an entity. It performs:
  1. Parallel web searches across multiple sources
  2. LLM analysis to filter and evaluate findings
  3. Risk scoring based on identified adverse media
  4. Structured reporting with source citations
This complements traditional watchlist checks by finding information that may not yet be in official sanctions lists.

Entity Types

The endpoint supports three entity types:
TypeDescriptionSearch Focus
personIndividual analysis (default)Fraud, sanctions, criminal records, professional profiles
companyCompany/organization analysisCorporate fraud, regulatory violations, sanctions
websiteWebsite/domain reputationFraud reports, security issues, blacklists, consumer complaints

Request Body Parameters

Request Example

curl -X POST https://stg.kyc.legaltalent.ai/kyc/adverse-media \
    -H "Authorization: Bearer YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "John Doe"
    }'

Additional Request Examples

Person with Context

curl -X POST https://stg.kyc.legaltalent.ai/kyc/adverse-media \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "entity_type": "person",
    "country": "US",
    "age": 45,
    "additional_info": "CEO of Tech Corp, based in New York"
  }'

Company Analysis

curl -X POST https://stg.kyc.legaltalent.ai/kyc/adverse-media \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Tech Corp Inc",
    "entity_type": "company",
    "country": "US",
    "additional_info": "Technology company founded in 2010"
  }'

Website/Domain Analysis

curl -X POST https://stg.kyc.legaltalent.ai/kyc/adverse-media \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "example-shop.com",
    "entity_type": "website",
    "additional_info": "E-commerce platform"
  }'

Using OpenAI Provider

curl -X POST https://stg.kyc.legaltalent.ai/kyc/adverse-media \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "country": "US",
    "provider": "openai",
    "model": "gpt-4o-mini"
  }'

Response Format

Success Response

{
  "final_risk_score": 75,
  "decision": "HIGH_RISK",
  "summary": "Multiple adverse media findings identified including fraud allegations and regulatory violations.",
  "sources": [
    {
      "id": 1,
      "title": "Tech Executive Charged with Fraud",
      "url": "https://example.com/news/article1",
      "summary": "John Doe, CEO of Tech Corp, faces fraud charges related to investor funds..."
    },
    {
      "id": 3,
      "title": "SEC Investigation into Tech Corp",
      "url": "https://example.com/news/article2",
      "summary": "SEC investigating Tech Corp for securities violations involving executive..."
    }
  ],
  "entity_name": "John Doe",
  "entity_type": "person",
  "country": "US",
  "age": 45,
  "analysis_timestamp": "2024-11-22T10:30:00Z",
  "processing_time_ms": 6000
}

Response Fields

FieldTypeDescription
final_risk_scoreintegerRisk score from 0-100 (higher = higher risk)
decisionstringRisk decision: CLEAR, LOW_RISK, MEDIUM_RISK, or HIGH_RISK
summarystringSummary of findings and risk assessment (max 300 chars)
sourcesarrayList of adverse media sources found (empty if CLEAR)
entity_namestringName of the analyzed entity
entity_typestringType of entity analyzed: person, company, or website
countrystringCountry (if provided)
ageintegerAge (if provided, 0 otherwise)
analysis_timestampstringISO 8601 timestamp of the analysis
processing_time_msintegerTotal processing time in milliseconds

Source Fields

Each source includes:
FieldTypeDescription
idintegerUnique source identifier (1-indexed)
titlestringTitle of the source/article (max 100 chars)
urlstringURL to the source
summarystringSummary explaining why this source is adverse (max 200 chars)

Decision Values

DecisionScore RangeDescription
CLEAR0-20No significant adverse media found
LOW_RISK21-40Minor adverse findings
MEDIUM_RISK41-70Moderate adverse findings requiring review
HIGH_RISK71-100Significant adverse findings, strong risk indicators

Clear Response (No Adverse Media)

{
  "final_risk_score": 5,
  "decision": "CLEAR",
  "summary": "No significant adverse media findings identified for this entity.",
  "sources": [],
  "entity_name": "John Doe",
  "entity_type": "person",
  "country": "US",
  "age": 45,
  "analysis_timestamp": "2024-11-22T10:30:00Z",
  "processing_time_ms": 5600
}

Website Analysis Response

{
  "final_risk_score": 65,
  "decision": "MEDIUM_RISK",
  "summary": "Multiple fraud reports and consumer complaints found for this website. Users report non-delivery of orders and poor customer service.",
  "sources": [
    {
      "id": 2,
      "title": "Scam Alert: example-shop.com Reviews",
      "url": "https://trustpilot.com/review/example-shop.com",
      "summary": "Multiple users report fraudulent charges and non-delivery of products..."
    },
    {
      "id": 5,
      "title": "BBB Complaints for Example Shop",
      "url": "https://bbb.org/example-shop",
      "summary": "37 complaints filed in the last 12 months regarding refund issues..."
    }
  ],
  "entity_name": "example-shop.com",
  "entity_type": "website",
  "country": "",
  "age": 0,
  "analysis_timestamp": "2024-11-22T10:30:00Z",
  "processing_time_ms": 5200
}

Error Responses

400 Bad Request - Missing Name

{
  "error": "Validation error: 'name' parameter is required"
}

400 Bad Request - Invalid Entity Type

{
  "error": "Validation error: 'entity_type' must be one of ['person', 'company', 'website']"
}

500 Internal Server Error - Configuration Error

{
  "error": "Configuration error: TAVILY_API_KEY not set"
}

500 Internal Server Error - Analysis Failed

{
  "error": "Internal error: Failed to analyze adverse media: LLM analysis timed out after 10 seconds"
}

Status Codes

CodeDescription
200Success - Analysis completed
400Bad Request - Invalid parameters
401Unauthorized - Missing or invalid token
403Forbidden - Insufficient permissions
500Internal Server Error

Usage Examples

Python Example

import requests

token = "YOUR_TOKEN"

# Analyze a person
response = requests.post(
    "https://stg.kyc.legaltalent.ai/kyc/adverse-media",
    headers={
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    },
    json={
        "name": "John Doe",
        "entity_type": "person",
        "country": "US",
        "age": 45,
        "additional_info": "CEO of Tech Corp"
    }
)

if response.status_code == 200:
    data = response.json()
    print(f"Risk Score: {data['final_risk_score']}")
    print(f"Decision: {data['decision']}")
    print(f"Summary: {data['summary']}")
    
    if data['sources']:
        print(f"\nFound {len(data['sources'])} adverse sources:")
        for source in data['sources']:
            print(f"- [{source['id']}] {source['title']}: {source['url']}")
else:
    print(f"Error: {response.json()}")

Python - Website Analysis

import requests

token = "YOUR_TOKEN"

# Analyze a website
response = requests.post(
    "https://stg.kyc.legaltalent.ai/kyc/adverse-media",
    headers={
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json"
    },
    json={
        "name": "suspicious-shop.com",
        "entity_type": "website",
        "additional_info": "E-commerce site selling electronics"
    }
)

if response.status_code == 200:
    data = response.json()
    print(f"Website: {data['entity_name']}")
    print(f"Risk Score: {data['final_risk_score']}")
    print(f"Decision: {data['decision']}")
    print(f"Summary: {data['summary']}")
else:
    print(f"Error: {response.json()}")

JavaScript Example

const token = "YOUR_TOKEN";

async function checkAdverseMedia(name, entityType = "person", options = {}) {
  const response = await fetch(
    "https://stg.kyc.legaltalent.ai/kyc/adverse-media",
    {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${token}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        name: name,
        entity_type: entityType,
        country: options.country,
        age: options.age,
        additional_info: options.additionalInfo
      })
    }
  );
  
  const data = await response.json();
  
  if (response.ok) {
    console.log(`Entity: ${data.entity_name} (${data.entity_type})`);
    console.log(`Risk Score: ${data.final_risk_score}`);
    console.log(`Decision: ${data.decision}`);
    console.log(`Summary: ${data.summary}`);
    
    if (data.sources.length > 0) {
      console.log(`\nFound ${data.sources.length} adverse sources`);
      data.sources.forEach(source => {
        console.log(`- [${source.id}] ${source.title}: ${source.url}`);
      });
    }
    
    return data;
  } else {
    console.error("Error:", data.error);
    throw new Error(data.error);
  }
}

// Usage examples
await checkAdverseMedia("John Doe", "person", { country: "US", age: 45 });
await checkAdverseMedia("Tech Corp Inc", "company", { country: "US" });
await checkAdverseMedia("example-shop.com", "website");

Search Process

Person/Company Analysis

The adverse media check for persons and companies performs parallel searches across:
  1. Fraud/Corruption/Sanctions: Financial crimes, corruption, sanctions, laundering
  2. Criminal Records: Arrests, investigations, charges, convictions
  3. Sanction Lists: OFAC, UN, designated persons, blacklists
  4. Professional Validation: LinkedIn, professional profiles, company associations
  5. General News: Recent news articles and media coverage

Website/Domain Analysis

For website analysis, specialized searches are performed:
  1. Reputation & Reviews: User reviews, complaints, ratings
  2. Fraud Reports: Scam reports, phishing alerts, fake site warnings
  3. Security Issues: Data breaches, vulnerabilities, malware reports
  4. Blacklists: Domain blacklists, spam lists, unsafe site flags
  5. Consumer Complaints: Trustpilot, BBB, consumer complaint databases
Results are then analyzed by an LLM to:
  • Filter false positives
  • Evaluate relevance to the specific entity
  • Assess risk factors
  • Generate concise summaries

Provider Options

AWS Bedrock (Default)

  • Provider: "bedrock"
  • Model: Claude 3.5 Haiku (with fallback to Claude 3 Haiku)
  • Use Case: Production deployments on AWS, no API key required (uses IAM role)

OpenAI

  • Provider: "openai"
  • Model: Specify model (default: "gpt-4o-mini")
  • Use Case: High-precision analysis, specific model requirements

Performance

  • Typical Response Time: 5-10 seconds
  • Timeout: 10 seconds per LLM call
  • Retries: Automatic retries on timeout (up to 3 attempts)
  • Search Sources: Up to 15 sources analyzed per request
  • LLM Analysis: Includes timeout protection and error handling

Integration Tips

  1. Combine with Watchlist Checks: Use adverse media as a supplement to traditional watchlist checks
  2. Use Context: Provide country, age, and additional info to improve accuracy
  3. Choose the Right Entity Type: Use website for domain reputation checks, company for organizational analysis
  4. Handle Timeouts: Implement retry logic for production use
  5. Review Scores: Risk scores should be reviewed by compliance teams, not automated
  6. Source Verification: Always verify adverse sources before making decisions

Best Practices

  • Use adverse media checks for:
    • Enhanced due diligence on individuals
    • Company/organization risk assessment
    • Website reputation verification before partnerships
    • Ongoing monitoring
    • Risk assessment for high-value relationships
    • Compliance investigations
  • Entity Type Selection:
    • Use person for individual background checks
    • Use company for corporate due diligence
    • Use website for merchant/partner website verification
  • Combine with traditional watchlist checks for comprehensive risk screening
  • Review summary for human-readable assessment
  • Check sources URLs to verify findings
  • Use risk scores as indicators, not definitive decisions