Webhooks API

Manage webhooks programmatically. Subscribe to specific event types and receive real-time notifications.

Webhook delivery model

Webhooks let you subscribe to lifecycle events across onboarding, responses, screening, verification, and cases. Use them to keep your systems in sync without polling.

Test autoflag events are simulated

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 TypeDescription
onboarding.createdOnboarding link generated and sent to the entity
onboarding.ddq_completedEntity finished the DDQ step within the onboarding session
onboarding.verification_completedEntity finished the identity verification step within the onboarding session
onboarding.completedAll required steps completed - entity fully onboarded
onboarding.expiredOnboarding link expired before entity completed all steps
onboarding.revokedOnboarding link permanently revoked by your team
onboarding.link_regeneratedA new token issued for an existing session (resend / refresh link)

Response Workflow Events

Event TypeDescription
response.createdNew response (DDQ submission) created
response.submittedEntity submitted completed response
response.reviewedResponse reviewed by compliance team
response.approvedResponse approved
response.rejectedResponse rejected
response.autofill_completedAI autofill process completed
response.check_answers_completedAI answer checking completed
response.autoflag_startedAI autoflag analysis started
response.autoflag_completedAI autoflag analysis completed
response.autoflag_failedAI autoflag analysis failed
response.assessment_generatedAI assessment report generated for a submitted response

Reports Events

Event TypeDescription
report.client_report_generatedEntity PDF client report generated successfully

AML Screening Events

Event TypeDescription
screening.completedAML screening check finished successfully
screening.failedAML screening encountered an error
batch.completedBatch screening operation completed
batch.progressBatch screening progress update
batch.failedBatch screening operation failed

Identity Verification Events

Event TypeDescription
verification.session_createdNew identity verification session started
verification.session_accessedVerification session accessed by entity
verification.session_completedVerification session completed successfully
verification.session_failedVerification session failed
verification.session_expiredVerification session expired
verification.check_completedIdentity verification check completed
non_document.check_initiatedNon-document check initiated
non_document.completedNon-document check completed with results
non_document.reviewedNon-document check reviewed

Case & Alert Events

Event TypeDescription
case.openedNew case opened for investigation
case.resolvedCase resolved or closed
alert.createdNew alert created

Special Event Types

Event TypeDescription
allSubscribe to all event types (wildcard subscription)
testSynthetic test event fired by the POST /api/v1/webhooks/test/POST /api/v2/webhooks/test/ endpoint

Event Grouping

{
  "event_groups": [
    "onboarding.*",
    "response.*",
    "screening.*",
    "verification.*",
    "case.*",
    "alert.*"
  ]
}

Create Webhook

POST /api/v2/webhooks/

Subscribe to a specific event type. Create multiple subscriptions to handle different events with different endpoints.

Request Body

FieldTypeRequiredDescription
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)
Save Your Secret Key

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

GET /api/v2/webhooks/

Get all webhook subscriptions for your API key. The v2 response uses the normalised {count, results} envelope.

Response Fields

FieldTypeDescription
iduuidWebhook identifier
event_typestringSubscribed event type
webhook_urlstringWebhook endpoint URL
is_activebooleanWhether webhook is active
descriptionstringWebhook description
filtersobjectEvent filters (if any)
created_atstringISO 8601 timestamp
statsobjectDelivery statistics
last_triggered_atstringLast 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

{
  "webhooks": [
    {
      "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",
      "stats": { "total_deliveries": 127, "successful_deliveries": 125, "failed_deliveries": 2 }
    }
  ]
}

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

GET /api/v2/webhooks/{webhook_id}/

Get detailed information about a specific webhook subscription.

Path Parameters

ParameterTypeDescription
webhook_iduuidWebhook 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

PATCH /api/v2/webhooks/{webhook_id}/

Update webhook settings. All fields are optional.

Path Parameters

ParameterTypeDescription
webhook_iduuidWebhook identifier

Request Body

FieldTypeDescription
webhook_urlstringNew webhook URL
is_activebooleanEnable/disable webhook
descriptionstringUpdated description
filtersobjectUpdated 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

DELETE /api/v2/webhooks/{webhook_id}/

Permanently delete a webhook. This action cannot be undone.

Path Parameters

ParameterTypeDescription
webhook_iduuidWebhook 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

POST /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

FieldTypeRequiredDescription
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

POST /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.

One-time secret

The new secret_key is only visible in this response and cannot be retrieved again. Store it securely before closing this request.

Path Parameters

ParameterTypeDescription
webhook_iduuidWebhook 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

GET /api/v2/webhooks/logs/

Retrieve the delivery log for all outgoing webhook events. Useful for debugging failed deliveries.

Query Parameters

ParameterTypeDescription
pageintegerPage number (default 1)
afterstringCursor for next page (from next_cursor)
page_sizeintegerResults per page (default 50, max 100)

Response Fields (per log entry)

FieldTypeDescription
iduuidLog entry ID - use with retry endpoint
event_typestringEvent that triggered this delivery
webhook_urlstringDestination URL
statusstringpending, delivered, failed, retrying
http_status_codeintegerHTTP status from your endpoint (null if no response)
attempt_numberintegerDelivery attempt count
error_messagestringError details if failed (null on success)
created_atstringISO 8601 timestamp
next_retry_atstringScheduled retry time (null if not retrying)

Retry a Failed Delivery

POST /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 - v1

{
  "total": 142,
  "page": 1,
  "page_size": 20,
  "logs": [
    {
      "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
    }
  ]
}

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' },
});