Batch Jobs
curl --request POST \
--url https://api.example.com/kyc/jobsimport requests
url = "https://api.example.com/kyc/jobs"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/kyc/jobs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/kyc/jobs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/kyc/jobs"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/kyc/jobs")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/kyc/jobs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyBatch Processing
Batch Jobs
POST
/
kyc
/
jobs
Batch Jobs
curl --request POST \
--url https://api.example.com/kyc/jobsimport requests
url = "https://api.example.com/kyc/jobs"
response = requests.post(url)
print(response.text)const options = {method: 'POST'};
fetch('https://api.example.com/kyc/jobs', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/kyc/jobs",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/kyc/jobs"
req, _ := http.NewRequest("POST", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/kyc/jobs")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/kyc/jobs")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
response = http.request(request)
puts response.read_bodyCreate and manage batch KYC validation jobs for processing multiple entities efficiently. Batch jobs allow you to submit large numbers of entities for validation and track their progress asynchronously.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /kyc/jobs | Create a new batch job |
GET | /kyc/jobs/{job_id} | Get job status and results |
Authentication
Requireskyc:create permission for creating jobs and kyc:read permission for retrieving job status. Include your Bearer token in the Authorization header.
Create Batch Job
Submit multiple entities for KYC validation in a single batch job.Endpoint
POST /kyc/jobs
Request Body Parameters
Request Example
curl -X POST https://stg.kyc.legaltalent.ai/kyc/jobs \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"entities": [
{
"entity_id": "e1",
"subject": {
"full_name": "John Doe",
"nationality": "US",
"birth_date": "1985-03-15"
},
"lists": ["ofac", "un"],
"search_type": "composite"
},
{
"entity_id": "e2",
"subject": {
"full_name": "Jane Smith",
"document_id": "12345678",
"document_type": "CI",
"nationality": "UY"
},
"lists": ["senaclaft_uy"]
}
]
}'
Response Format
{
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"total_entities": 2,
"status": "processing",
"created_at": "2024-11-22T10:30:00Z",
"estimated_completion": "2024-11-22T10:35:00Z"
}
Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Always "success" when job is created |
job_id | string | Unique identifier for the batch job |
total_entities | integer | Number of entities in the batch |
status | string | Job status: "processing", "completed", "failed" |
created_at | string | ISO 8601 timestamp when job was created |
estimated_completion | string | Estimated completion time (ISO 8601) |
Get Job Status
Retrieve the status and results of a batch job.Endpoint
GET /kyc/jobs/{job_id}
Path Parameters
Request Example
curl https://stg.kyc.legaltalent.ai/kyc/jobs/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer YOUR_TOKEN"
Response Format - Processing
{
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"job_status": "processing",
"total_entities": 2,
"processed_entities": 1,
"completed_entities": 1,
"failed_entities": 0,
"matches_found": 0,
"created_at": "2024-11-22T10:30:00Z",
"updated_at": "2024-11-22T10:32:00Z",
"estimated_completion": "2024-11-22T10:35:00Z"
}
Response Format - Completed
{
"status": "success",
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"job_status": "completed",
"total_entities": 2,
"processed_entities": 2,
"completed_entities": 2,
"failed_entities": 0,
"matches_found": 1,
"created_at": "2024-11-22T10:30:00Z",
"completed_at": "2024-11-22T10:34:00Z",
"results": [
{
"entity_id": "e1",
"status": "completed",
"is_match": false,
"match_count": 0,
"matches": []
},
{
"entity_id": "e2",
"status": "completed",
"is_match": true,
"match_count": 1,
"matches": [
{
"entity_id": "12345",
"name": "Jane Smith",
"confidence_score": 0.95,
"match_type": "composite",
"source_list": "senaclaft_uy",
"programs": ["PEP"]
}
]
}
]
}
Response Fields
| Field | Type | Description |
|---|---|---|
status | string | Response status: "success" |
job_id | string | Unique identifier for the batch job |
job_status | string | Job status: "processing", "completed", "failed" |
total_entities | integer | Total number of entities in the batch |
processed_entities | integer | Number of entities processed so far |
completed_entities | integer | Number of entities successfully completed |
failed_entities | integer | Number of entities that failed processing |
matches_found | integer | Total number of matches found across all entities |
created_at | string | ISO 8601 timestamp when job was created |
completed_at | string | ISO 8601 timestamp when job completed (if completed) |
updated_at | string | ISO 8601 timestamp of last update |
estimated_completion | string | Estimated completion time (if processing) |
results | array | Array of entity results (only present when completed) |
Entity Result Object
| Field | Type | Description |
|---|---|---|
entity_id | string | Entity identifier (if provided) |
status | string | Entity processing status |
is_match | boolean | Whether any matches were found |
match_count | integer | Number of matches found |
matches | array | Array of match objects (same format as single check) |
Error Responses
400 Bad Request - Invalid Entities
{
"error": "Invalid entities",
"message": "Entity at index 0 must have a non-empty 'subject.full_name' field"
}
400 Bad Request - Too Many Entities
{
"error": "Too many entities",
"message": "Maximum 10,000 entities per job"
}
404 Not Found - Job Not Found
{
"error": "Job not found",
"message": "Job ID does not exist or belongs to a different tenant"
}
Status Codes
| Code | Description |
|---|---|
| 200 | Success - Job created or retrieved |
| 400 | Bad Request - Invalid parameters |
| 401 | Unauthorized - Missing or invalid token |
| 403 | Forbidden - Insufficient permissions |
| 404 | Not Found - Job not found |
| 500 | Internal Server Error |
Usage Examples
Python Example
import requests
import time
token = "YOUR_TOKEN"
# Create batch job
response = requests.post(
"https://stg.kyc.legaltalent.ai/kyc/jobs",
headers={
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
},
json={
"entities": [
{
"entity_id": "e1",
"subject": {
"full_name": "John Doe",
"nationality": "US"
},
"lists": ["ofac"]
},
{
"entity_id": "e2",
"subject": {
"full_name": "Jane Smith",
"nationality": "UY"
},
"lists": ["senaclaft_uy"]
}
]
}
)
if response.status_code == 200:
job_data = response.json()
job_id = job_data["job_id"]
print(f"Job created: {job_id}")
# Poll for completion
while True:
status_response = requests.get(
f"https://stg.kyc.legaltalent.ai/kyc/jobs/{job_id}",
headers={"Authorization": f"Bearer {token}"}
)
if status_response.status_code == 200:
status_data = status_response.json()
print(f"Status: {status_data['job_status']} - {status_data['processed_entities']}/{status_data['total_entities']}")
if status_data['job_status'] == 'completed':
print(f"Matches found: {status_data['matches_found']}")
for result in status_data['results']:
if result['is_match']:
print(f"Entity {result['entity_id']}: {result['match_count']} matches")
break
elif status_data['job_status'] == 'failed':
print("Job failed")
break
time.sleep(5) # Poll every 5 seconds
else:
print(f"Error: {response.json()}")
JavaScript Example
const token = "YOUR_TOKEN";
async function createBatchJob(entities) {
// Create job
const createResponse = await fetch(
"https://stg.kyc.legaltalent.ai/kyc/jobs",
{
method: "POST",
headers: {
"Authorization": `Bearer ${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify({ entities })
}
);
const jobData = await createResponse.json();
if (!createResponse.ok) {
throw new Error(jobData.error);
}
const jobId = jobData.job_id;
console.log(`Job created: ${jobId}`);
// Poll for completion
while (true) {
const statusResponse = await fetch(
`https://stg.kyc.legaltalent.ai/kyc/jobs/${jobId}`,
{
headers: {
"Authorization": `Bearer ${token}`
}
}
);
const statusData = await statusResponse.json();
console.log(`Status: ${statusData.job_status} - ${statusData.processed_entities}/${statusData.total_entities}`);
if (statusData.job_status === 'completed') {
console.log(`Matches found: ${statusData.matches_found}`);
statusData.results.forEach(result => {
if (result.is_match) {
console.log(`Entity ${result.entity_id}: ${result.match_count} matches`);
}
});
return statusData;
} else if (statusData.job_status === 'failed') {
throw new Error("Job failed");
}
// Wait 5 seconds before polling again
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
Best Practices
- Batch Size: Keep batches between 100-1,000 entities for optimal performance
- Entity IDs: Always provide
entity_idto track individual entities in results - Polling: Poll job status every 5-10 seconds (don’t poll too frequently)
- Error Handling: Handle failed entities appropriately
- Rate Limits: Be aware of API rate limits when creating multiple jobs
Performance
- Processing Time: Approximately 1-2 seconds per entity
- Maximum Entities: 10,000 entities per job
- Chunking: Large batches are automatically chunked for processing
- Concurrent Processing: Entities are processed in parallel for faster completion
Job Statuses
| Status | Description |
|---|---|
processing | Job is currently being processed |
completed | All entities have been processed successfully |
failed | Job failed (check error details) |
Integration Tips
- Async Processing: Batch jobs are processed asynchronously - don’t wait for completion
- Status Polling: Implement exponential backoff for status polling
- Result Storage: Store job results for audit and compliance purposes
- Error Recovery: Implement retry logic for failed entities