curl -X GET 'https://verification.didit.me/v3/session/22222222-3333-4444-5555-666666666666/webhook/66666666-7777-8888-9999-000000000001' \
-H 'x-api-key: YOUR_API_KEY'import json
import os
import requests
session_id = '22222222-3333-4444-5555-666666666666'
webhook_uuid = '66666666-7777-8888-9999-000000000001'
resp = requests.get(
f'https://verification.didit.me/v3/session/{session_id}/webhook/{webhook_uuid}', # no trailing slash
headers={'x-api-key': os.environ['DIDIT_API_KEY']},
timeout=10,
)
resp.raise_for_status()
delivery = resp.json()
headers = json.loads(delivery['request_header'])
payload = json.loads(delivery['request_body'])
print(delivery['response_status'], headers['X-Signature-V2'], payload['status'])const sessionId = '22222222-3333-4444-5555-666666666666';
const webhookUuid = '66666666-7777-8888-9999-000000000001';
// No trailing slash on this path.
const resp = await fetch(`https://verification.didit.me/v3/session/${sessionId}/webhook/${webhookUuid}`, {
headers: { 'x-api-key': process.env.DIDIT_API_KEY },
});
if (!resp.ok) throw new Error(`Request failed: ${resp.status}`);
const delivery = await resp.json();
const payload = JSON.parse(delivery.request_body);
console.log(delivery.response_status, payload.status);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"uuid": "66666666-7777-8888-9999-000000000001",
"session_id": "22222222-3333-4444-5555-666666666666",
"request_url": "https://yourapp.com/webhooks/didit",
"response_status": 503,
"status": "In Progress",
"webhook_type": "status.updated",
"request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"a5e02a03404e1337a0198e6be15d34abbd053c658a0e51e5d0e78554213ef29b\", \"X-Signature-V2\": \"927e7cb770c94ce745939bff73f04aa200015f3bc64795ba46c2aaf78a6cedc5\", \"X-Signature-Simple\": \"e37b0d4c716c72bb5ae7127b9cc455d28ab4686e9e22312b4ec2327409a73302\", \"X-Timestamp\": \"1792056078\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
"request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792056078,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}",
"created_at": "2026-10-15T09:21:18.412345Z"
}Get Session Webhook Delivery
Retrieve one webhook delivery of a session: the URL, your endpoint’s HTTP answer, and the exact signature headers and JSON body Didit sent.
curl -X GET 'https://verification.didit.me/v3/session/22222222-3333-4444-5555-666666666666/webhook/66666666-7777-8888-9999-000000000001' \
-H 'x-api-key: YOUR_API_KEY'import json
import os
import requests
session_id = '22222222-3333-4444-5555-666666666666'
webhook_uuid = '66666666-7777-8888-9999-000000000001'
resp = requests.get(
f'https://verification.didit.me/v3/session/{session_id}/webhook/{webhook_uuid}', # no trailing slash
headers={'x-api-key': os.environ['DIDIT_API_KEY']},
timeout=10,
)
resp.raise_for_status()
delivery = resp.json()
headers = json.loads(delivery['request_header'])
payload = json.loads(delivery['request_body'])
print(delivery['response_status'], headers['X-Signature-V2'], payload['status'])const sessionId = '22222222-3333-4444-5555-666666666666';
const webhookUuid = '66666666-7777-8888-9999-000000000001';
// No trailing slash on this path.
const resp = await fetch(`https://verification.didit.me/v3/session/${sessionId}/webhook/${webhookUuid}`, {
headers: { 'x-api-key': process.env.DIDIT_API_KEY },
});
if (!resp.ok) throw new Error(`Request failed: ${resp.status}`);
const delivery = await resp.json();
const payload = JSON.parse(delivery.request_body);
console.log(delivery.response_status, payload.status);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-api-key: <api-key>"
],
]);
$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://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}")
.header("x-api-key", "<api-key>")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/session/{sessionId}/webhook/{webhook_uuid}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["x-api-key"] = '<api-key>'
response = http.request(request)
puts response.read_body{
"uuid": "66666666-7777-8888-9999-000000000001",
"session_id": "22222222-3333-4444-5555-666666666666",
"request_url": "https://yourapp.com/webhooks/didit",
"response_status": 503,
"status": "In Progress",
"webhook_type": "status.updated",
"request_header": "{\"Content-Type\": \"application/json\", \"X-Signature\": \"a5e02a03404e1337a0198e6be15d34abbd053c658a0e51e5d0e78554213ef29b\", \"X-Signature-V2\": \"927e7cb770c94ce745939bff73f04aa200015f3bc64795ba46c2aaf78a6cedc5\", \"X-Signature-Simple\": \"e37b0d4c716c72bb5ae7127b9cc455d28ab4686e9e22312b4ec2327409a73302\", \"X-Timestamp\": \"1792056078\", \"User-Agent\": \"DiditWebhook/2.0 +https://didit.me\"}",
"request_body": "{\"application_id\":\"aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee\",\"created_at\":1792056057,\"environment\":\"live\",\"event_id\":\"33333333-4444-5555-6666-777777777777\",\"sandbox_scenario\":null,\"session_id\":\"22222222-3333-4444-5555-666666666666\",\"status\":\"In Progress\",\"timestamp\":1792056078,\"vendor_data\":\"user-123\",\"webhook_type\":\"status.updated\",\"workflow_id\":\"44444444-5555-6666-7777-888888888888\",\"workflow_version\":3}",
"created_at": "2026-10-15T09:21:18.412345Z"
}request_body is the one described in Webhooks, and the headers are the ones covered in signature verification. To send the delivery again, use Resend session webhook delivery.Authorizations
Your application's API key, from Developers -> API keys in the Business Console. The primary key has full access. A named key can be scoped: none, read or write per resource, limited to some workflows or to approved sessions, to a list of IP addresses, and to an expiry date. 401 means the key is missing, wrong, revoked or expired; 403 means the key has no access to this resource or action, or the request came from an address outside its IP list; 404 on a session route means the session is outside the key's workflows or statuses. A key without media access receives image, video and PDF URLs as null, and a key without sessions write receives session links and tokens as null. See https://docs.didit.me/console/api-keys.
Path Parameters
UUID of the verification session, user (KYC) or business (KYB): the session_id returned by POST /v3/session/. The server resolves it against both session types.
Must be a valid UUID. The route only matches well-formed UUIDs, so a malformed value is rejected by the URL router before any application code runs and the response is a 404 HTML page rather than the JSON {"detail": ...} envelope shown below.
UUID of the delivery: the uuid of an entry returned by GET /v3/session/{sessionId}/webhooks/. It must belong to the session in the path.
Response
The delivery, with its request headers and body.
One webhook delivery attempt recorded for a verification session, with the exact request headers and body Didit sent.
Delivery ID. Use it as {webhook_uuid} to get or resend this delivery.
The session the delivery belongs to (the session in the path).
URL the delivery was sent to.
HTTP status your endpoint returned. null while the delivery is queued and not yet attempted. When no HTTP answer was received Didit records a status of its own: 504 when your endpoint did not answer within 5 seconds, 503 for a connection failure, 400 when the URL was refused as unsafe (for example a private or internal address), and 404 for any other request error. 400 or above counts as a failed delivery.
Session status when the event was generated, for example In Progress, Approved or Declined.
Supported webhook event name. Use these exact strings in subscribed_events; unsupported values are rejected.
status.updated, data.updated, user.status.updated, user.data.updated, business.status.updated, business.data.updated, activity.created, transaction.created, transaction.status.updated, travel_rule.status.updated, workflow.compliance_changed, auth.signup, auth.login, auth.login_failed, auth.password_reset_requested, auth.password_reset_completed, auth.mfa_changed, auth.new_device, auth.account_locked, investigator.report.ready, investigator.decision.automated, investigator.decision.overridden, investigator.decision.contested, investigator.question.raised, investigator.automation.paused, investigator.rfi.answered, investigator.rfi.overdue, investigator.drift.detected, investigator.sla.breached, investigator.qa.failed, investigator.external.report.ready JSON text (a string) of the request headers Didit sent: Content-Type, X-Signature, X-Signature-V2, X-Signature-Simple, X-Timestamp and User-Agent. Parse it with a JSON parser. It holds signatures, never the signing secret.
JSON text (a string) of the exact payload Didit sent, keys sorted, including event_id and timestamp. Parse it with a JSON parser; see Payload shape. For a scoped key without media: read, media URLs inside it are null; without sessions: write, session tokens and hosted verification links are null. A body changed that way no longer matches its signatures. Didit does not record the response body your endpoint returned.
When the delivery was created.