curl -X POST https://verification.didit.me/v1/transactions/ \
-H 'X-Transaction-Token: SDK_TOKEN' -H 'Content-Type: application/json' \
-d '{"txnId": "wd-2026-07-07-0042", "type": "travelRule", "info": {"direction": "out", "amount": "0.25", "currency": "ETH", "currencyType": "crypto"}, "subject": {"fullName": "Jane Doe"}, "counterparty": {"fullName": "Ana Diaz", "paymentMethod": {"type": "unhosted_wallet", "accountId": "0xBeneficiaryWallet01"}}, "travelRule": {"status": "AWAITING_COUNTERPARTY", "beneficiaryData": {"wallet_address": "0xBeneficiaryWallet01", "name": "Ana Diaz"}}, "includeCryptoScreening": true}'import { DiditSdk } from '@didit-protocol/sdk-web';
const result = await DiditSdk.shared.submitTransaction({
transactionToken: sdkToken,
transaction: {
txnId: 'wd-2026-07-07-0042',
category: 'travelRule',
details: { direction: 'out', amount: '0.25', currency: 'ETH', currencyType: 'crypto' },
subject: { fullName: 'Jane Doe' },
counterparty: { fullName: 'Ana Diaz', paymentMethod: { type: 'unhosted_wallet', accountId: '0xBeneficiaryWallet01' } },
travelRule: { status: 'AWAITING_COUNTERPARTY', beneficiaryData: { wallet_address: '0xBeneficiaryWallet01', name: 'Ana Diaz' } },
includeCryptoScreening: true
},
onActionCompleted: (refreshed) => console.log(refreshed.status)
});import requests
url = "https://verification.didit.me/v1/transactions/"
payload = {
"txnId": "wd-2026-07-07-0042",
"type": "travelRule",
"info": {
"direction": "out",
"amount": "0.25",
"currency": "ETH",
"currencyType": "crypto",
"cryptoParams": { "crypto_chain": "ETH" }
},
"subject": { "fullName": "Jane Doe" },
"counterparty": {
"fullName": "Ana Diaz",
"paymentMethod": {
"type": "unhosted_wallet",
"accountId": "0xBeneficiaryWallet01"
}
},
"travelRule": {
"status": "AWAITING_COUNTERPARTY",
"beneficiaryData": {
"wallet_address": "0xBeneficiaryWallet01",
"name": "Ana Diaz"
}
},
"includeCryptoScreening": True
}
headers = {
"X-Transaction-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v1/transactions/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'txnId' => 'wd-2026-07-07-0042',
'type' => 'travelRule',
'info' => [
'direction' => 'out',
'amount' => '0.25',
'currency' => 'ETH',
'currencyType' => 'crypto',
'cryptoParams' => [
'crypto_chain' => 'ETH'
]
],
'subject' => [
'fullName' => 'Jane Doe'
],
'counterparty' => [
'fullName' => 'Ana Diaz',
'paymentMethod' => [
'type' => 'unhosted_wallet',
'accountId' => '0xBeneficiaryWallet01'
]
],
'travelRule' => [
'status' => 'AWAITING_COUNTERPARTY',
'beneficiaryData' => [
'wallet_address' => '0xBeneficiaryWallet01',
'name' => 'Ana Diaz'
]
],
'includeCryptoScreening' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Transaction-Token: <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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://verification.didit.me/v1/transactions/"
payload := strings.NewReader("{\n \"txnId\": \"wd-2026-07-07-0042\",\n \"type\": \"travelRule\",\n \"info\": {\n \"direction\": \"out\",\n \"amount\": \"0.25\",\n \"currency\": \"ETH\",\n \"currencyType\": \"crypto\",\n \"cryptoParams\": {\n \"crypto_chain\": \"ETH\"\n }\n },\n \"subject\": {\n \"fullName\": \"Jane Doe\"\n },\n \"counterparty\": {\n \"fullName\": \"Ana Diaz\",\n \"paymentMethod\": {\n \"type\": \"unhosted_wallet\",\n \"accountId\": \"0xBeneficiaryWallet01\"\n }\n },\n \"travelRule\": {\n \"status\": \"AWAITING_COUNTERPARTY\",\n \"beneficiaryData\": {\n \"wallet_address\": \"0xBeneficiaryWallet01\",\n \"name\": \"Ana Diaz\"\n }\n },\n \"includeCryptoScreening\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Transaction-Token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://verification.didit.me/v1/transactions/")
.header("X-Transaction-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"txnId\": \"wd-2026-07-07-0042\",\n \"type\": \"travelRule\",\n \"info\": {\n \"direction\": \"out\",\n \"amount\": \"0.25\",\n \"currency\": \"ETH\",\n \"currencyType\": \"crypto\",\n \"cryptoParams\": {\n \"crypto_chain\": \"ETH\"\n }\n },\n \"subject\": {\n \"fullName\": \"Jane Doe\"\n },\n \"counterparty\": {\n \"fullName\": \"Ana Diaz\",\n \"paymentMethod\": {\n \"type\": \"unhosted_wallet\",\n \"accountId\": \"0xBeneficiaryWallet01\"\n }\n },\n \"travelRule\": {\n \"status\": \"AWAITING_COUNTERPARTY\",\n \"beneficiaryData\": {\n \"wallet_address\": \"0xBeneficiaryWallet01\",\n \"name\": \"Ana Diaz\"\n }\n },\n \"includeCryptoScreening\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v1/transactions/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Transaction-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"txnId\": \"wd-2026-07-07-0042\",\n \"type\": \"travelRule\",\n \"info\": {\n \"direction\": \"out\",\n \"amount\": \"0.25\",\n \"currency\": \"ETH\",\n \"currencyType\": \"crypto\",\n \"cryptoParams\": {\n \"crypto_chain\": \"ETH\"\n }\n },\n \"subject\": {\n \"fullName\": \"Jane Doe\"\n },\n \"counterparty\": {\n \"fullName\": \"Ana Diaz\",\n \"paymentMethod\": {\n \"type\": \"unhosted_wallet\",\n \"accountId\": \"0xBeneficiaryWallet01\"\n }\n },\n \"travelRule\": {\n \"status\": \"AWAITING_COUNTERPARTY\",\n \"beneficiaryData\": {\n \"wallet_address\": \"0xBeneficiaryWallet01\",\n \"name\": \"Ana Diaz\"\n }\n },\n \"includeCryptoScreening\": true\n}"
response = http.request(request)
puts response.read_body{
"uuid": "22222222-3333-4444-5555-666666666666",
"txn_id": "wd-2026-07-07-0042",
"transaction_type": "travelRule",
"direction": "OUTBOUND",
"status": "AWAITING_USER",
"amount": "0.25",
"currency": "ETH",
"travel_rule": {
"uuid": "33333333-4444-5555-6666-777777777777",
"status": "ON_HOLD",
"required": true
},
"action_required": {
"type": "wallet_ownership",
"url": "https://verification.didit.me/wallet-ownership/3s9x...urlsafe",
"widget_session_id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
"expires_at": "2026-07-07T13:00:00Z"
}
}Submit Transaction (SDK Token)
Device-facing endpoint the Didit SDKs call to submit a transaction directly from the end-user’s device. Authentication is a scoped token from POST /v3/transactions/sdk-token/ sent in the X-Transaction-Token header instead of an API key, and the endpoint is CORS-enabled so browsers can call it cross-origin. The payload uses the camelCase wire aliases shown below (the SDK submitTransaction methods build it for you). Three server-side guarantees: the application is always taken from the token; the subject identity (externalUserId) is always enforced from the token’s vendor_data, so spoofed payload values are ignored; and device intelligence (the SDK device fingerprint plus server-derived IP and user agent) is attached to the subject automatically.
curl -X POST https://verification.didit.me/v1/transactions/ \
-H 'X-Transaction-Token: SDK_TOKEN' -H 'Content-Type: application/json' \
-d '{"txnId": "wd-2026-07-07-0042", "type": "travelRule", "info": {"direction": "out", "amount": "0.25", "currency": "ETH", "currencyType": "crypto"}, "subject": {"fullName": "Jane Doe"}, "counterparty": {"fullName": "Ana Diaz", "paymentMethod": {"type": "unhosted_wallet", "accountId": "0xBeneficiaryWallet01"}}, "travelRule": {"status": "AWAITING_COUNTERPARTY", "beneficiaryData": {"wallet_address": "0xBeneficiaryWallet01", "name": "Ana Diaz"}}, "includeCryptoScreening": true}'import { DiditSdk } from '@didit-protocol/sdk-web';
const result = await DiditSdk.shared.submitTransaction({
transactionToken: sdkToken,
transaction: {
txnId: 'wd-2026-07-07-0042',
category: 'travelRule',
details: { direction: 'out', amount: '0.25', currency: 'ETH', currencyType: 'crypto' },
subject: { fullName: 'Jane Doe' },
counterparty: { fullName: 'Ana Diaz', paymentMethod: { type: 'unhosted_wallet', accountId: '0xBeneficiaryWallet01' } },
travelRule: { status: 'AWAITING_COUNTERPARTY', beneficiaryData: { wallet_address: '0xBeneficiaryWallet01', name: 'Ana Diaz' } },
includeCryptoScreening: true
},
onActionCompleted: (refreshed) => console.log(refreshed.status)
});import requests
url = "https://verification.didit.me/v1/transactions/"
payload = {
"txnId": "wd-2026-07-07-0042",
"type": "travelRule",
"info": {
"direction": "out",
"amount": "0.25",
"currency": "ETH",
"currencyType": "crypto",
"cryptoParams": { "crypto_chain": "ETH" }
},
"subject": { "fullName": "Jane Doe" },
"counterparty": {
"fullName": "Ana Diaz",
"paymentMethod": {
"type": "unhosted_wallet",
"accountId": "0xBeneficiaryWallet01"
}
},
"travelRule": {
"status": "AWAITING_COUNTERPARTY",
"beneficiaryData": {
"wallet_address": "0xBeneficiaryWallet01",
"name": "Ana Diaz"
}
},
"includeCryptoScreening": True
}
headers = {
"X-Transaction-Token": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v1/transactions/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'txnId' => 'wd-2026-07-07-0042',
'type' => 'travelRule',
'info' => [
'direction' => 'out',
'amount' => '0.25',
'currency' => 'ETH',
'currencyType' => 'crypto',
'cryptoParams' => [
'crypto_chain' => 'ETH'
]
],
'subject' => [
'fullName' => 'Jane Doe'
],
'counterparty' => [
'fullName' => 'Ana Diaz',
'paymentMethod' => [
'type' => 'unhosted_wallet',
'accountId' => '0xBeneficiaryWallet01'
]
],
'travelRule' => [
'status' => 'AWAITING_COUNTERPARTY',
'beneficiaryData' => [
'wallet_address' => '0xBeneficiaryWallet01',
'name' => 'Ana Diaz'
]
],
'includeCryptoScreening' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Transaction-Token: <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"
"strings"
"net/http"
"io"
)
func main() {
url := "https://verification.didit.me/v1/transactions/"
payload := strings.NewReader("{\n \"txnId\": \"wd-2026-07-07-0042\",\n \"type\": \"travelRule\",\n \"info\": {\n \"direction\": \"out\",\n \"amount\": \"0.25\",\n \"currency\": \"ETH\",\n \"currencyType\": \"crypto\",\n \"cryptoParams\": {\n \"crypto_chain\": \"ETH\"\n }\n },\n \"subject\": {\n \"fullName\": \"Jane Doe\"\n },\n \"counterparty\": {\n \"fullName\": \"Ana Diaz\",\n \"paymentMethod\": {\n \"type\": \"unhosted_wallet\",\n \"accountId\": \"0xBeneficiaryWallet01\"\n }\n },\n \"travelRule\": {\n \"status\": \"AWAITING_COUNTERPARTY\",\n \"beneficiaryData\": {\n \"wallet_address\": \"0xBeneficiaryWallet01\",\n \"name\": \"Ana Diaz\"\n }\n },\n \"includeCryptoScreening\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Transaction-Token", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://verification.didit.me/v1/transactions/")
.header("X-Transaction-Token", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"txnId\": \"wd-2026-07-07-0042\",\n \"type\": \"travelRule\",\n \"info\": {\n \"direction\": \"out\",\n \"amount\": \"0.25\",\n \"currency\": \"ETH\",\n \"currencyType\": \"crypto\",\n \"cryptoParams\": {\n \"crypto_chain\": \"ETH\"\n }\n },\n \"subject\": {\n \"fullName\": \"Jane Doe\"\n },\n \"counterparty\": {\n \"fullName\": \"Ana Diaz\",\n \"paymentMethod\": {\n \"type\": \"unhosted_wallet\",\n \"accountId\": \"0xBeneficiaryWallet01\"\n }\n },\n \"travelRule\": {\n \"status\": \"AWAITING_COUNTERPARTY\",\n \"beneficiaryData\": {\n \"wallet_address\": \"0xBeneficiaryWallet01\",\n \"name\": \"Ana Diaz\"\n }\n },\n \"includeCryptoScreening\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v1/transactions/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Transaction-Token"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"txnId\": \"wd-2026-07-07-0042\",\n \"type\": \"travelRule\",\n \"info\": {\n \"direction\": \"out\",\n \"amount\": \"0.25\",\n \"currency\": \"ETH\",\n \"currencyType\": \"crypto\",\n \"cryptoParams\": {\n \"crypto_chain\": \"ETH\"\n }\n },\n \"subject\": {\n \"fullName\": \"Jane Doe\"\n },\n \"counterparty\": {\n \"fullName\": \"Ana Diaz\",\n \"paymentMethod\": {\n \"type\": \"unhosted_wallet\",\n \"accountId\": \"0xBeneficiaryWallet01\"\n }\n },\n \"travelRule\": {\n \"status\": \"AWAITING_COUNTERPARTY\",\n \"beneficiaryData\": {\n \"wallet_address\": \"0xBeneficiaryWallet01\",\n \"name\": \"Ana Diaz\"\n }\n },\n \"includeCryptoScreening\": true\n}"
response = http.request(request)
puts response.read_body{
"uuid": "22222222-3333-4444-5555-666666666666",
"txn_id": "wd-2026-07-07-0042",
"transaction_type": "travelRule",
"direction": "OUTBOUND",
"status": "AWAITING_USER",
"amount": "0.25",
"currency": "ETH",
"travel_rule": {
"uuid": "33333333-4444-5555-6666-777777777777",
"status": "ON_HOLD",
"required": true
},
"action_required": {
"type": "wallet_ownership",
"url": "https://verification.didit.me/wallet-ownership/3s9x...urlsafe",
"widget_session_id": "77777777-8888-9999-aaaa-bbbbbbbbbbbb",
"expires_at": "2026-07-07T13:00:00Z"
}
}Authorizations
Short-lived scoped token minted by your backend via POST /v3/transactions/sdk-token/. Used by the Didit SDKs on the device-facing /v1/transactions/ endpoints.
Body
Your unique identifier for this transaction (maps to transaction_id, max 128 characters).
"wd-2026-07-07-0042"
Transaction category (maps to transaction_category), e.g. finance, kyc, travelRule, userPlatformEvent, gamblingBet.
"travelRule"
Core financial details of the transaction (maps to transaction_details).
Show child attributes
Show child attributes
The subject (applicant) of the transaction. externalUserId is ignored here: the subject identity is always enforced from the token's vendor_data.
Show child attributes
Show child attributes
When the transaction occurred (maps to transaction_at). Defaults to now if omitted.
IANA time zone identifier (maps to time_zone), e.g. Europe/Madrid.
The counterparty of the transaction (optional). Same shape as subject; externalUserId is meaningful here.
Show child attributes
Show child attributes
Custom key-value pairs (maps to custom_properties). Each key can be referenced in rule conditions as custom_values.<key>.
Travel Rule details (maps to travel_rule_details). When Travel Rule is enabled for the application, Didit ignores any status you send and drives the exchange itself.
Show child attributes
Show child attributes
Per-transaction override for crypto blockchain analytics screening (maps to include_crypto_screening).
The didit-fp-v2 device fingerprint payload. Injected automatically by the SDKs; only relevant when calling the wire API directly.
Response
Transaction submitted and monitored. Same detail shape as GET /v3/transactions/{transaction_id}/, including the action_required block when the end user must complete a follow-up action (the SDKs auto-launch it by default).
Full monitoring record for one transaction, as returned by GET /v3/transactions/{transaction_id}/ and POST /v3/transactions/.
Didit-stable transaction identifier. Use as {transaction_id} for follow-up calls.
Environment of the application that owns the transaction. A sandbox transaction is stored but never evaluated, screened, notified or billed, so its empty rule_runs means "not evaluated".
live, sandbox Application-scoped sequential transaction number shown in Console (e.g. 4123).
The transaction_id you supplied at create time (max 128 chars). Unique per application.
When the transaction occurred (from transaction_at; defaults to submission time).
IANA time zone identifier provided at create time.
Top-level category as stored: finance, kyc, travelRule, userPlatformEvent, gamblingBet, gamblingLimitChange, gamblingBonusChange, auditTrailEvent. Note multi-word values are echoed back in camelCase even when submitted in snake_case.
Sub-type within the category (e.g. deposit, withdrawal, transfer). Defaults to the category when not supplied.
Direction relative to the subject. Stored uppercase regardless of the casing submitted (in/out/inbound/outbound are accepted on input).
INBOUND, OUTBOUND Current monitoring verdict. Transactions are created APPROVED; rules may flip them to IN_REVIEW/DECLINED synchronously.
APPROVED, IN_REVIEW, DECLINED, AWAITING_USER How the record originated: LIVE for transactions submitted through the API or SDK, IMPORTED for transactions loaded through the console import.
LIVE, IMPORTED Transaction amount as a decimal string with trailing zeros stripped (e.g. "1500", "0.5", "0.123456789012345678"). Up to 18 decimal places.
Currency code of amount. Any ISO 4217 alphabetic code is accepted (e.g. EUR, USD, NGN), as is a crypto asset symbol (e.g. BTC). Prefer a currently-circulating code. Not every accepted code has an exchange rate: when none is available for the code (for example the ISO accounting unit XSU, or a crypto symbol Didit does not price), automatic conversion fails and preferred_currency_amount is returned null unless the request supplied a pre-converted amount_in_default_currency.
fiat or crypto, as submitted in currency_kind.
Pre-converted amount you supplied, as a decimal string with trailing zeros stripped.
amount converted to the application's preferred currency, when available.
Free-text payment reference or memo from the submission.
External payment system reference (e.g. blockchain transaction hash) from payment_reference_id.
Risk score accumulated by rules (typically 0–100). Higher = riskier.
Categorical risk severity set by rules/providers (UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL). null until something sets it.
UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL Machine-readable reason for the current status.
Human-readable label for decision_reason_code.
Convenience copy of the applicant's vendor_data.
Snapshot of the subject and counterparty payloads as submitted at create time.
The custom_properties you supplied at create time. Each key is addressable in rule conditions as custom_values.<key>.
Tags attached to the transaction (manually or by rules).
Show child attributes
Show child attributes
Transaction parties (applicant, counterparty).
Show child attributes
Show child attributes
Payment methods linked to the transaction.
Show child attributes
Show child attributes
Files attached to the transaction from the console. [] when none.
Show child attributes
Show child attributes
Activity log entries (creation, notes, manual reviews, status changes).
Show child attributes
Show child attributes
Alerts raised by rules and providers.
Show child attributes
Show child attributes
Per-rule execution results — which rule fired, with what score impact.
Show child attributes
Show child attributes
Raw provider payloads (AML screening, blockchain analytics, etc.).
Show child attributes
Show child attributes
Travel Rule transfer or check. Populated when travel_rule_details was submitted, and also when Travel Rule is enabled and the transaction was created with transaction_category: travelRule (Didit initiates the exchange itself, even without travel_rule_details). null when no transfer or check exists.
Show child attributes
Show child attributes
Graph snapshot of related transactions/parties used by the rules engine. Either the network_snapshot submitted with the transaction or the graph Didit builds from a successful AML wallet screening (which replaces a submitted one). null when neither exists.
Show child attributes
Show child attributes
Remediation session offered to the user when re-verification is required. Superseded by action_required, which is the canonical block; kept for backward compatibility.
Show child attributes
Show child attributes
Pending end-user action required to complete this transaction, or null when there is none. The Didit SDKs auto-launch the action by default and refresh the transaction when it finishes. Two variants, discriminated by type: verification_session (a hosted verification session created by a rule action) and wallet_ownership (a wallet-ownership widget session auto-minted for a Travel Rule transfer that needs proof of wallet control, gated by the auto_wallet_verification Travel Rule setting). When both could apply, wallet_ownership takes precedence because it blocks the Travel Rule exchange.
- Verification session
- Wallet ownership
Show child attributes
Show child attributes
Cost of this transaction: total_price and items, one per charge, each with usage_type, price, details and created_at. A re-screen of the same transaction is a new item.