Webhooks API
Manage webhooks programmatically. Subscribe to specific event types and receive real-time notifications.
Webhooks let you subscribe to lifecycle events across onboarding, responses, screening, verification, and cases. Use them to keep your systems in sync without polling.
When using a test API key, response.autoflag_started and response.autoflag_completed are delivered without consuming credits. The completed payload includes "simulated": true and empty counts because no AI analysis runs on synthetic data.
Event Types
Subscribe to specific events or use all to receive every event.
Onboarding Session Events
High-level lifecycle events for the magic-link container sent to an entity that may wrap a DDQ response, an identity verification, or both.
| Event Type | Description |
|---|---|
onboarding.created | Onboarding link generated and sent to the entity |
onboarding.ddq_completed | Entity finished the DDQ step within the onboarding session |
onboarding.verification_completed | Entity finished the identity verification step within the onboarding session |
onboarding.completed | All required steps completed - entity fully onboarded |
onboarding.expired | Onboarding link expired before entity completed all steps |
onboarding.revoked | Onboarding link permanently revoked by your team |
onboarding.link_regenerated | A new token issued for an existing session (resend / refresh link) |
Response Workflow Events
| Event Type | Description |
|---|---|
response.created | New response (DDQ submission) created |
response.submitted | Entity submitted completed response |
response.reviewed | Response reviewed by compliance team |
response.approved | Response approved |
response.rejected | Response rejected |
response.autofill_completed | AI autofill process completed |
response.check_answers_completed | AI answer checking completed |
response.autoflag_started | AI autoflag analysis started |
response.autoflag_completed | AI autoflag analysis completed |
response.autoflag_failed | AI autoflag analysis failed |
response.assessment_generated | AI assessment report generated for a submitted response |
Reports Events
| Event Type | Description |
|---|---|
report.client_report_generated | Entity PDF client report generated successfully |
AML Screening Events
| Event Type | Description |
|---|---|
screening.completed | AML screening check finished successfully |
screening.failed | AML screening encountered an error |
batch.completed | Batch screening operation completed |
batch.progress | Batch screening progress update |
batch.failed | Batch screening operation failed |
Identity Verification Events
| Event Type | Description |
|---|---|
verification.session_created | New identity verification session started |
verification.session_accessed | Verification session accessed by entity |
verification.session_completed | Verification session completed successfully |
verification.session_failed | Verification session failed |
verification.session_expired | Verification session expired |
verification.check_completed | Identity verification check completed |
non_document.check_initiated | Non-document check initiated |
non_document.completed | Non-document check completed with results |
non_document.reviewed | Non-document check reviewed |
Case & Alert Events
| Event Type | Description |
|---|---|
case.opened | New case opened for investigation |
case.resolved | Case resolved or closed |
alert.created | New alert created |
Special Event Types
| Event Type | Description |
|---|---|
all | Subscribe to all event types (wildcard subscription) |
test | Synthetic test event fired by the POST /api/v2/webhooks/test/ endpoint |
Event Grouping
{
"event_groups": [
"onboarding.*",
"response.*",
"screening.*",
"verification.*",
"case.*",
"alert.*"
]
}
Create Webhook
/api/v2/webhooks/
Subscribe to a specific event type. Create multiple subscriptions to handle different events with different endpoints.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
event_type |
string | Yes | Event type to subscribe to (see event types table above) |
webhook_url |
string | Yes | Your webhook endpoint URL (must be HTTPS) |
description |
string | No | Human-readable description |
filters |
object | No | Optional event filters (for future use) |
The secret_key is returned only once during creation. Store it securely to verify webhook signatures.
Create Webhook
curl -X POST https://api.kycgenie.com/api/v1/webhooks/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"description": "Production screening webhook"
}'
curl -X POST https://api.kycgenie.com/api/v2/webhooks/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"description": "Production screening webhook"
}'
import requests, uuid
resp = requests.post(
"https://api.kycgenie.com/api/v2/webhooks/",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"description": "Production screening webhook",
},
)
webhook = resp.json()
print(f"Subscription ID: {webhook['id']}")
print(f"Secret: {webhook['secret_key']}") # Save this!
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
webhook = client.webhooks.create_subscription(
event_type="screening.completed",
webhook_url="https://api.yourcompany.com/webhooks/screening",
description="Production screening webhook",
)
print(f"Subscription ID: {webhook.webhook_id}")
print(f"Secret: {webhook.secret_key}") # Save this!
const resp = await fetch('https://api.kycgenie.com/api/v1/webhooks/', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
event_type: 'screening.completed',
webhook_url: 'https://api.yourcompany.com/webhooks/screening',
description: 'Production screening webhook',
}),
});
const webhook = await resp.json();
console.log(`Subscription ID: ${webhook.webhook_id}`);
console.log(`Secret: ${webhook.secret_key}`); // Save this!
const resp = await fetch('https://api.kycgenie.com/api/v2/webhooks/', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
event_type: 'screening.completed',
webhook_url: 'https://api.yourcompany.com/webhooks/screening',
description: 'Production screening webhook',
}),
});
const webhook = await resp.json();
console.log(`Subscription ID: ${webhook.webhook_id}`);
console.log(`Secret: ${webhook.secret_key}`); // Save this!
Response (201 Created)
{
"webhook_id": "f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"secret_key": "whsec_A1B2C3D4E5F6G7H8I9J0K1L2M3N4O5P6Q7R8S9T0U1V2W3X4Y5Z6",
"message": "Webhook created successfully"
}
List Webhooks
/api/v2/webhooks/
Get all webhook subscriptions for your API key. The v2 response uses the normalised {count, results} envelope.
Response Fields
| Field | Type | Description |
|---|---|---|
id | uuid | Webhook identifier |
event_type | string | Subscribed event type |
webhook_url | string | Webhook endpoint URL |
is_active | boolean | Whether webhook is active |
description | string | Webhook description |
filters | object | Event filters (if any) |
created_at | string | ISO 8601 timestamp |
stats | object | Delivery statistics |
last_triggered_at | string | Last delivery timestamp (null if never triggered) |
List Webhooks
curl https://api.kycgenie.com/api/v1/webhooks/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/webhooks/ \
-H "Authorization: Bearer YOUR_API_KEY"
import requests
# v1 returns {webhooks: [...]}, v2 returns {count, results: [...]}
resp = requests.get(
"https://api.kycgenie.com/api/v2/webhooks/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
data = resp.json()
for sub in data["results"]:
print(f"{sub['event_type']}: {sub['webhook_url']}")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
data = client.webhooks.list_subscriptions()
for sub in data.results:
print(f"{sub.event_type}: {sub.webhook_url}")
const resp = await fetch('https://api.kycgenie.com/api/v1/webhooks/', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});
const { webhooks } = await resp.json();
webhooks.forEach(s => console.log(`${s.event_type}: ${s.webhook_url}`));
const resp = await fetch('https://api.kycgenie.com/api/v2/webhooks/', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});
const { results } = await resp.json();
results.forEach(s => console.log(`${s.event_type}: ${s.webhook_url}`));
Response
{
"count": 1,
"results": [
{
"id": "f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"is_active": true,
"description": "Production screening webhook",
"filters": {},
"created_at": "2026-01-19T10:30:00.000Z",
"stats": { "total_deliveries": 127, "successful_deliveries": 125, "failed_deliveries": 2 },
"last_triggered_at": "2026-01-22T08:15:30.000Z"
}
]
}
Get Webhook
/api/v2/webhooks/{webhook_id}/
Get detailed information about a specific webhook subscription.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
webhook_id | uuid | Webhook identifier |
Get Webhook
curl https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/ \
-H "Authorization: Bearer YOUR_API_KEY"
resp = requests.get(
"https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.json())
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
webhook = client.webhooks.get_details(
webhook_id="f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
)
print(webhook.event_type, webhook.is_active)
const resp = await fetch(
'https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
const resp = await fetch(
'https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/',
{ headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(await resp.json());
Response Example
{
"id": "f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"is_active": true,
"description": "Production screening webhook",
"filters": {},
"created_at": "2026-01-19T10:30:00.123456+00:00",
"updated_at": "2026-01-19T10:30:00.123456+00:00",
"stats": {
"total_deliveries": 127,
"successful_deliveries": 125,
"failed_deliveries": 2
},
"last_triggered_at": "2026-01-22T08:15:30.987654+00:00"
}
Update Webhook
/api/v2/webhooks/{webhook_id}/
Update webhook settings. All fields are optional.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
webhook_id | uuid | Webhook identifier |
Request Body
| Field | Type | Description |
|---|---|---|
webhook_url | string | New webhook URL |
is_active | boolean | Enable/disable webhook |
description | string | Updated description |
filters | object | Updated filters |
Update Webhook
curl -X PATCH https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"is_active": false}'
curl -X PATCH https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"is_active": false}'
resp = requests.patch(
"https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"is_active": False},
)
print(resp.json()["message"])
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.webhooks.update(
webhook_id="f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
is_active=False,
)
print(result.message)
const resp = await fetch(
'https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/',
{
method: 'PATCH',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ is_active: false }),
}
);
console.log((await resp.json()).message);
const resp = await fetch(
'https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/',
{
method: 'PATCH',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ is_active: false }),
}
);
console.log((await resp.json()).message);
Response
{
"message": "Webhook updated",
"id": "f67f165d-0d1e-4eb7-81e6-3494a260dcd4"
}
Delete Webhook
/api/v2/webhooks/{webhook_id}/
Permanently delete a webhook. This action cannot be undone.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
webhook_id | uuid | Webhook identifier |
Delete Webhook
curl -X DELETE https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl -X DELETE https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/ \
-H "Authorization: Bearer YOUR_API_KEY"
resp = requests.delete(
"https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.status_code) # 200
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
client.webhooks.delete(
webhook_id="f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
)
const resp = await fetch(
'https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/',
{ method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(resp.status); // 200
const resp = await fetch(
'https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/',
{ method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
console.log(resp.status); // 200
Response
{
"message": "Webhook deleted successfully"
}
Test Webhook
/api/v2/webhooks/test/
Synchronously deliver a test event to the given URL and return the outcome.
Delivery happens inline - no Celery worker is required. Accepts both API key and session (browser) authentication.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
webhook_url |
string | Yes | HTTPS URL to deliver the test event to |
Test Webhook
curl -X POST https://api.kycgenie.com/api/v1/webhooks/test/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://example.com/webhook-receiver"}'
curl -X POST https://api.kycgenie.com/api/v2/webhooks/test/ \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://example.com/webhook-receiver"}'
resp = requests.post(
"https://api.kycgenie.com/api/v2/webhooks/test/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={"webhook_url": "https://example.com/webhook-receiver"},
)
print(resp.json())
from kycgenie import KYCGenie, KYCGenieAPIError
client = KYCGenie(api_key="YOUR_API_KEY")
try:
result = client.webhooks.test_delivery(
webhook_url="https://example.com/webhook-receiver",
)
print(f"Delivered - remote status: {result.http_status_code}")
except KYCGenieAPIError as e:
if e.http_status == 502:
# KYCGenie reached the URL but it returned a non-2xx, or was unreachable
remote_status = (e.details or {}).get('http_status_code', 'unreachable')
print(f"Webhook URL returned HTTP {remote_status} - {e.data.error}")
else:
print(f"Error {e.http_status}: {e.code} - {e}")
const resp = await fetch('https://api.kycgenie.com/api/v1/webhooks/test/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ webhook_url: 'https://example.com/webhook-receiver' }),
});
console.log(await resp.json());
const resp = await fetch('https://api.kycgenie.com/api/v2/webhooks/test/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({ webhook_url: 'https://example.com/webhook-receiver' }),
});
console.log(await resp.json());
Success Example
{
"success": true,
"message": "Test webhook delivered successfully",
"http_status_code": 200
}
Failure Example (502)
{
"error": "server_error",
"message": "Webhook endpoint returned HTTP 404",
"details": {
"http_status_code": 404
}
}
Rotate Webhook Secret
/api/v2/webhooks/{webhook_id}/rotate-secret/
Generate a new HMAC signing secret for a webhook subscription. The new secret is returned once only - store it immediately. Update your receiver to use the new secret before the old one is discarded.
The new secret_key is only visible in this response and cannot be retrieved again. Store it securely before closing this request.
Path Parameters
| Parameter | Type | Description |
|---|---|---|
webhook_id | uuid | Webhook to rotate the secret for |
Rotate Secret
curl -X POST https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/rotate-secret/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl -X POST https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/rotate-secret/ \
-H "Authorization: Bearer YOUR_API_KEY"
resp = requests.post(
"https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/rotate-secret/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
new_secret = resp.json()["secret_key"]
print(f"New secret: {new_secret}") # Save this immediately!
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.webhooks.rotate_secret(
webhook_id="f67f165d-0d1e-4eb7-81e6-3494a260dcd4",
)
print(f"New secret: {result.secret_key}") # Save this immediately!
const resp = await fetch(
'https://api.kycgenie.com/api/v1/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/rotate-secret/',
{ method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { secret_key } = await resp.json();
console.log('New secret:', secret_key); // Save this immediately!
const resp = await fetch(
'https://api.kycgenie.com/api/v2/webhooks/f67f165d-0d1e-4eb7-81e6-3494a260dcd4/rotate-secret/',
{ method: 'POST', headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { secret_key } = await resp.json();
console.log('New secret:', secret_key); // Save this immediately!
Response
{
"secret_key": "whsec_NEW_SECRET_VALUE_HERE",
"message": "Webhook secret rotated successfully"
}
Webhook Logs
/api/v2/webhooks/logs/
Retrieve the delivery log for all outgoing webhook events. Useful for debugging failed deliveries.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
after | string | Cursor for next page (from next_cursor) |
page_size | integer | Results per page (default 50, max 100) |
Response Fields (per log entry)
| Field | Type | Description |
|---|---|---|
id | uuid | Log entry ID - use with retry endpoint |
event_type | string | Event that triggered this delivery |
webhook_url | string | Destination URL |
status | string | pending, delivered, failed, retrying |
http_status_code | integer | HTTP status from your endpoint (null if no response) |
attempt_number | integer | Delivery attempt count |
error_message | string | Error details if failed (null on success) |
created_at | string | ISO 8601 timestamp |
next_retry_at | string | Scheduled retry time (null if not retrying) |
Retry a Failed Delivery
/api/v2/webhooks/logs/{log_id}/retry/
Manually re-deliver a specific log entry. Use the id from the logs list.
List Logs
curl "https://api.kycgenie.com/api/v1/webhooks/logs/?page_size=20" \
-H "Authorization: Bearer YOUR_API_KEY"
curl "https://api.kycgenie.com/api/v2/webhooks/logs/?page_size=20" \
-H "Authorization: Bearer YOUR_API_KEY"
resp = requests.get(
"https://api.kycgenie.com/api/v2/webhooks/logs/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
params={"page_size": 20},
)
data = resp.json()
for log in data["results"]:
print(f"{log['event_type']} → {log['status']} ({log['http_status_code']})")
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
data = client.webhooks.list_logs(page_size=20)
for log in data.results:
print(f"{log.event_type} → {log.status} ({log.http_status_code})")
# Paginate
if data.has_more:
next_page = client.webhooks.list_logs(after=data.next_cursor)
const resp = await fetch('https://api.kycgenie.com/api/v1/webhooks/logs/?page_size=20', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});
const data = await resp.json();
data.logs.forEach(l => console.log(`${l.event_type} → ${l.status}`));
const resp = await fetch('https://api.kycgenie.com/api/v2/webhooks/logs/?page_size=20', {
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});
const { results, has_more, next_cursor } = await resp.json();
results.forEach(l => console.log(`${l.event_type} → ${l.status}`));
Response
{
"has_more": true,
"next_cursor": "eyJpZCI6IDEyMzR9",
"prev_cursor": null,
"results": [
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"event_type": "screening.completed",
"webhook_url": "https://api.yourcompany.com/webhooks/screening",
"status": "failed",
"http_status_code": 500,
"attempt_number": 3,
"error_message": "Server error",
"created_at": "2026-06-12T14:30:00.000Z",
"next_retry_at": null
}
]
}
Retry a Delivery
from kycgenie import KYCGenie
client = KYCGenie(api_key="YOUR_API_KEY")
result = client.webhooks.retry(
log_id="a1b2c3d4-e5f6-7890-abcd-ef1234567890",
)
print(result.message)
curl -X POST https://api.kycgenie.com/api/v1/webhooks/logs/a1b2c3d4-e5f6-7890-abcd-ef1234567890/retry/ \
-H "Authorization: Bearer YOUR_API_KEY"
curl -X POST https://api.kycgenie.com/api/v2/webhooks/logs/a1b2c3d4-e5f6-7890-abcd-ef1234567890/retry/ \
-H "Authorization: Bearer YOUR_API_KEY"
resp = requests.post(
"https://api.kycgenie.com/api/v2/webhooks/logs/a1b2c3d4-e5f6-7890-abcd-ef1234567890/retry/",
headers={"Authorization": "Bearer YOUR_API_KEY"},
)
print(resp.json()["message"])
await fetch('https://api.kycgenie.com/api/v1/webhooks/logs/a1b2c3d4-e5f6-7890-abcd-ef1234567890/retry/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});
await fetch('https://api.kycgenie.com/api/v2/webhooks/logs/a1b2c3d4-e5f6-7890-abcd-ef1234567890/retry/', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
});