diff --git a/openapi/SOURCE.json b/openapi/SOURCE.json index 689d545..f67b1ab 100644 --- a/openapi/SOURCE.json +++ b/openapi/SOURCE.json @@ -1,8 +1,8 @@ { "verification.json": { "url": "https://docs.didit.me/openapi-25.json", - "sha256": "da776b2226bd264797268988b179f37b906c0b2e4953a16111c0d4296c89fcd4", - "fetched_at": "2026-10-23T22:27:22Z" + "sha256": "6157d174fff4e0093ca7ac8e0f064ffc777d1cfa4a7eeb2b0e88fbf86f4a060b", + "fetched_at": "2026-10-26T07:02:08Z" }, "account.json": { "url": "https://docs.didit.me/openapi-auth.json", diff --git a/openapi/verification.json b/openapi/verification.json index a3d5eea..0236ac8 100644 --- a/openapi/verification.json +++ b/openapi/verification.json @@ -23847,7 +23847,7 @@ }, "beneficiary_data": { "type": "object", - "description": "Beneficiary party, as flat fields or one IVMS 101 person. An empty `wallet_address` is filled from `counterparty.payment_method.account_id`. It must be an object: anything else is a `400`. On a memo network `memo` names the beneficiary wallet's memo or tag; `wallet_address` and `memo` win over the counterparty's payment method." + "description": "Beneficiary party, as flat fields or one IVMS 101 person. It must be an object: anything else is a `400`. To route the transfer, Didit reads `wallet_address` (an empty one is filled from `counterparty.payment_method.account_id`), `chain` (filled from `transaction_details.crypto_params.crypto_chain` or the `currency` when that names a supported chain), `name` (falling back to `counterparty.full_name`), `travel_address`, `counterparty_vasp_name`, `counterparty_vasp_lei` and `counterparty_vasp_email`. On a memo network `memo` names the beneficiary wallet's memo or tag; `wallet_address` and `memo` win over the counterparty's payment method." }, "metadata": { "type": "object" @@ -63212,7 +63212,7 @@ "/v3/session/{sessionId}/kyb/parties/{partyUuid}/regenerate/": { "post": { "summary": "Regenerate a Key People party's KYC session", - "description": "Give a Key People party of a Business Verification (KYB) session a new individual KYC session after its previous one was deleted, so the Key People check can finish again; send no request body. It works only when the party's KYC session was deleted (`kyc_session_deleted: true`): a party whose KYC session still exists (in any status), a party that never had one, or a company party returns `409`. Didit creates a new hosted KYC session with the workflow the deleted one ran (its latest published version) or, when that is no longer known, the workflow your Key People settings assign to the party's role, emails the link to the party when an email is on file, clears `is_skipped`, and recomputes the Key People check and the business session status. It then sends a `data.updated` [webhook](https://docs.didit.me/integration/webhooks) for the business session with trigger `console_key_people_regenerate`; to exempt the party instead, use `PATCH /v3/session/{sessionId}/kyb/parties/{partyUuid}/`. A scoped API key needs `decisions: write`, and without `sessions: write` it receives `kyc_session_url` as `null`.", + "description": "Give a Key People party of a Business Verification (KYB) session a new individual KYC session after its previous one was deleted or expired before the person started it, so the Key People check can finish again; send no request body. It works when the party's KYC session was deleted (`kyc_session_deleted: true`) or expired before the person started it (`Expired`, never started). A session still in progress or one that ended in any other status (`Approved`, `Declined`, `In Review`, `Abandoned`, ...) returns `409` unless it was deleted. A party that never had one or a company party always returns `409`. Didit creates a new hosted KYC session with the workflow the party was verified with (its latest published version) or, when that is no longer known, the workflow your Key People settings assign to the party's role, so its link lasts that KYC workflow's session expiration time; it emails the link to the party when an email is on file, clears `is_skipped`, and recomputes the Key People check and the business session status. It then sends a `data.updated` [webhook](https://docs.didit.me/integration/webhooks) for the business session with trigger `console_key_people_regenerate`; to exempt the party instead, use `PATCH /v3/session/{sessionId}/kyb/parties/{partyUuid}/`. A scoped API key needs `decisions: write`, and without `sessions: write` it receives `kyc_session_url` as `null`. Deleted sessions qualify even if the person had already started or finished verification. Imported sessions do not qualify through expiry; they must have been deleted.", "operationId": "post_v3_session_kyb_party_regenerate", "x-didit-sdk": { "resource": "sessions", @@ -63266,7 +63266,7 @@ ], "responses": { "200": { - "description": "New KYC session created. Returns the updated party with its new child session.", + "description": "New KYC session created. Returns the updated party with its new child session, which expires after its KYC workflow's session expiration time.", "content": { "application/json": { "schema": { @@ -63436,7 +63436,7 @@ } }, "409": { - "description": "The party's KYC session was not deleted (it still exists, the party never had one, or the party is a company), so there is nothing to replace. Branch on `code`.", + "description": "The party has no eligible KYC session to replace. Unless deleted, a session still in progress or one that ended in another status (`Approved`, `Declined`, `In Review`, `Abandoned`, ...) cannot be regenerated. A party that never had one or a company party also returns `409`. An eligible session was deleted or expired before the person started it. Deleted sessions qualify even if the person had already started or finished verification. Imported sessions do not qualify through expiry; they must have been deleted. Branch on `code`.", "content": { "application/json": { "schema": { @@ -63460,7 +63460,7 @@ } }, "example": { - "detail": "This party's KYC session has not been deleted, so it cannot be regenerated.", + "detail": "This party's KYC session is still live (it has neither been deleted nor expired without starting), so it cannot be regenerated.", "code": "kyb_party_kyc_session_not_deleted" } } @@ -76432,7 +76432,7 @@ "TEST_VASP", null ], - "description": "The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered a sandbox application's transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response." + "description": "The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered the sandbox transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response." }, "protocol": { "type": "string", @@ -96264,7 +96264,7 @@ ] }, "TravelRuleStatusUpdatedEvent": { - "description": "A Travel Rule exchange changed status. Sent on every transition up to and including `FINISHED`, `CANCELLED` or `EXPIRED`, never after. Sent for live applications only. There is no top-level `status`.", + "description": "A Travel Rule exchange changed status. Sent on every transition up to and including `FINISHED`, `CANCELLED` or `EXPIRED`, never after. Sent for live applications and, for Travel Rule exchanges, for sandbox applications too (`environment: sandbox`). There is no top-level `status`.", "allOf": [ { "$ref": "#/components/schemas/WebhookEventEnvelope" @@ -96318,9 +96318,18 @@ "TRUST", "VERIFYVASP", "SYGNA", - "EMAIL" + "EMAIL", + "TEST_VASP" ], - "description": "Network the exchange runs on, or an empty string when none could be resolved." + "description": "Network the exchange runs on, or an empty string when none could be resolved. `TEST_VASP` is a sandbox transfer the Didit Test VASP answered." + }, + "test_vasp": { + "type": "boolean", + "description": "Present and `true` only on a sandbox transfer the Didit Test VASP answered." + }, + "test_vasp_scenario": { + "type": "string", + "description": "Present only with `test_vasp`: the sandbox scenario that decided the outcome, or an empty string." }, "direction": { "type": "string", @@ -105202,7 +105211,7 @@ "travel_rule.status.updated": { "post": { "summary": "Travel Rule status changed", - "description": "A Travel Rule exchange changed status. Sent on every transition up to and including `FINISHED`, `CANCELLED` or `EXPIRED`, never after. Sent for live applications only. There is no top-level `status`.", + "description": "A Travel Rule exchange changed status. Sent on every transition up to and including `FINISHED`, `CANCELLED` or `EXPIRED`, never after. Sent for live applications and, for Travel Rule exchanges, for sandbox applications too (`environment: sandbox`). There is no top-level `status`.", "tags": [ "Webhook" ], diff --git a/src/main/java/me/didit/resources/SessionsResource.java b/src/main/java/me/didit/resources/SessionsResource.java index ef88f9b..67b367d 100644 --- a/src/main/java/me/didit/resources/SessionsResource.java +++ b/src/main/java/me/didit/resources/SessionsResource.java @@ -1686,7 +1686,7 @@ public CompletableFuture updateDocumentAiD /** * Regenerate a Key People party's KYC session * - *

Give a Key People party of a Business Verification (KYB) session a new individual KYC session after its previous one was deleted, so the Key People check can finish again; send no request body. It works only when the party's KYC session was deleted (kyc_session_deleted: true): a party whose KYC session still exists (in any status), a party that never had one, or a company party returns 409. Didit creates a new hosted KYC session with the workflow the deleted one ran (its latest published version) or, when that is no longer known, the workflow your Key People settings assign to the party's role, emails the link to the party when an email is on file, clears is_skipped, and recomputes the Key People check and the business session status. It then sends a data.updated webhook for the business session with trigger console_key_people_regenerate; to exempt the party instead, use PATCH /v3/session/{sessionId}/kyb/parties/{partyUuid}/. A scoped API key needs decisions: write, and without sessions: write it receives kyc_session_url as null. + *

Give a Key People party of a Business Verification (KYB) session a new individual KYC session after its previous one was deleted or expired before the person started it, so the Key People check can finish again; send no request body. It works when the party's KYC session was deleted (kyc_session_deleted: true) or expired before the person started it (Expired, never started). A session still in progress or one that ended in any other status (Approved, Declined, In Review, Abandoned, ...) returns 409 unless it was deleted. A party that never had one or a company party always returns 409. Didit creates a new hosted KYC session with the workflow the party was verified with (its latest published version) or, when that is no longer known, the workflow your Key People settings assign to the party's role, so its link lasts that KYC workflow's session expiration time; it emails the link to the party when an email is on file, clears is_skipped, and recomputes the Key People check and the business session status. It then sends a data.updated webhook for the business session with trigger console_key_people_regenerate; to exempt the party instead, use PATCH /v3/session/{sessionId}/kyb/parties/{partyUuid}/. A scoped API key needs decisions: write, and without sessions: write it receives kyc_session_url as null. Deleted sessions qualify even if the person had already started or finished verification. Imported sessions do not qualify through expiry; they must have been deleted. * *

{@code POST /v3/session/{sessionId}/kyb/parties/{partyUuid}/regenerate/} * diff --git a/src/main/java/me/didit/types/TransactionsCreateParams.java b/src/main/java/me/didit/types/TransactionsCreateParams.java index a08b48d..84174ed 100644 --- a/src/main/java/me/didit/types/TransactionsCreateParams.java +++ b/src/main/java/me/didit/types/TransactionsCreateParams.java @@ -2900,7 +2900,7 @@ public Optional> originatorData() { } /** - * Beneficiary party, as flat fields or one IVMS 101 person. An empty wallet_address is filled from counterparty.payment_method.account_id. It must be an object: anything else is a 400. On a memo network memo names the beneficiary wallet's memo or tag; wallet_address and memo win over the counterparty's payment method. + * Beneficiary party, as flat fields or one IVMS 101 person. It must be an object: anything else is a 400. To route the transfer, Didit reads wallet_address (an empty one is filled from counterparty.payment_method.account_id), chain (filled from transaction_details.crypto_params.crypto_chain or the currency when that names a supported chain), name (falling back to counterparty.full_name), travel_address, counterparty_vasp_name, counterparty_vasp_lei and counterparty_vasp_email. On a memo network memo names the beneficiary wallet's memo or tag; wallet_address and memo win over the counterparty's payment method. * * @return the value, or empty when the field is absent or null * @throws me.didit.errors.UnexpectedResponseException when the field has another type @@ -3023,7 +3023,7 @@ public Builder originatorData(Map originatorData) { } /** - * Beneficiary party, as flat fields or one IVMS 101 person. An empty wallet_address is filled from counterparty.payment_method.account_id. It must be an object: anything else is a 400. On a memo network memo names the beneficiary wallet's memo or tag; wallet_address and memo win over the counterparty's payment method. + * Beneficiary party, as flat fields or one IVMS 101 person. It must be an object: anything else is a 400. To route the transfer, Didit reads wallet_address (an empty one is filled from counterparty.payment_method.account_id), chain (filled from transaction_details.crypto_params.crypto_chain or the currency when that names a supported chain), name (falling back to counterparty.full_name), travel_address, counterparty_vasp_name, counterparty_vasp_lei and counterparty_vasp_email. On a memo network memo names the beneficiary wallet's memo or tag; wallet_address and memo win over the counterparty's payment method. * * @param beneficiaryData the value * @return this builder diff --git a/src/main/java/me/didit/types/TravelRuleStatusUpdatedEvent.java b/src/main/java/me/didit/types/TravelRuleStatusUpdatedEvent.java index eaa6e2d..c4f8f2f 100644 --- a/src/main/java/me/didit/types/TravelRuleStatusUpdatedEvent.java +++ b/src/main/java/me/didit/types/TravelRuleStatusUpdatedEvent.java @@ -15,10 +15,10 @@ import org.jspecify.annotations.Nullable; /** - * A Travel Rule exchange changed status. Sent on every transition up to and including FINISHED, CANCELLED or EXPIRED, never after. Sent for live applications only. There is no top-level status. + * A Travel Rule exchange changed status. Sent on every transition up to and including FINISHED, CANCELLED or EXPIRED, never after. Sent for live applications and, for Travel Rule exchanges, for sandbox applications too (environment: sandbox). There is no top-level status. */ public final class TravelRuleStatusUpdatedEvent extends JsonModel { - private static final Set KNOWN_FIELDS = Set.of("event_id", "timestamp", "created_at", "application_id", "environment", "webhook_type", "transaction_id", "txn_id", "travel_rule_status", "rail", "direction"); + private static final Set KNOWN_FIELDS = Set.of("event_id", "timestamp", "created_at", "application_id", "environment", "webhook_type", "transaction_id", "txn_id", "travel_rule_status", "rail", "test_vasp", "test_vasp_scenario", "direction"); private TravelRuleStatusUpdatedEvent(ObjectNode json, Map> files) { super(json, files); @@ -144,7 +144,7 @@ public TravelRuleStatusUpdatedEvent.TravelRuleStatus travelRuleStatus() { } /** - * Network the exchange runs on, or an empty string when none could be resolved. + * Network the exchange runs on, or an empty string when none could be resolved. TEST_VASP is a sandbox transfer the Didit Test VASP answered. * * @return the value * @throws me.didit.errors.UnexpectedResponseException when the field is absent or has another type @@ -153,6 +153,26 @@ public TravelRuleStatusUpdatedEvent.Rail rail() { return Json.required(json, "rail", Conv.enumeration(TravelRuleStatusUpdatedEvent.Rail::of)); } + /** + * Present and true only on a sandbox transfer the Didit Test VASP answered. + * + * @return the value, or empty when the field is absent or null + * @throws me.didit.errors.UnexpectedResponseException when the field has another type + */ + public Optional testVasp() { + return Json.optional(json, "test_vasp", Conv.BOOLEAN); + } + + /** + * Present only with test_vasp: the sandbox scenario that decided the outcome, or an empty string. + * + * @return the value, or empty when the field is absent or null + * @throws me.didit.errors.UnexpectedResponseException when the field has another type + */ + public Optional testVaspScenario() { + return Json.optional(json, "test_vasp_scenario", Conv.STRING); + } + /** * Direction of the transfer. * @@ -267,7 +287,7 @@ public Builder travelRuleStatus(TravelRuleStatusUpdatedEvent.TravelRuleStatus tr } /** - * Network the exchange runs on, or an empty string when none could be resolved. + * Network the exchange runs on, or an empty string when none could be resolved. TEST_VASP is a sandbox transfer the Didit Test VASP answered. * * @param rail the value * @return this builder @@ -276,6 +296,26 @@ public Builder rail(TravelRuleStatusUpdatedEvent.Rail rail) { return set("rail", Conv.enumeration(TravelRuleStatusUpdatedEvent.Rail::of), rail); } + /** + * Present and true only on a sandbox transfer the Didit Test VASP answered. + * + * @param testVasp the value + * @return this builder + */ + public Builder testVasp(boolean testVasp) { + return set("test_vasp", Conv.BOOLEAN, testVasp); + } + + /** + * Present only with test_vasp: the sandbox scenario that decided the outcome, or an empty string. + * + * @param testVaspScenario the value + * @return this builder + */ + public Builder testVaspScenario(String testVaspScenario) { + return set("test_vasp_scenario", Conv.STRING, testVaspScenario); + } + /** * Direction of the transfer. * @@ -430,7 +470,7 @@ public boolean isKnown() { } /** - * Network the exchange runs on, or an empty string when none could be resolved. + * Network the exchange runs on, or an empty string when none could be resolved. TEST_VASP is a sandbox transfer the Didit Test VASP answered. * *

An open enum: {@link #of(String)} accepts values this SDK version does not know yet. */ @@ -459,7 +499,10 @@ public static final class Rail extends StringEnum { /** The value {@code "EMAIL"}. */ public static final Rail EMAIL = new Rail("EMAIL"); - private static final List KNOWN_VALUES = List.of(EMPTY, INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA, EMAIL); + /** The value {@code "TEST_VASP"}. */ + public static final Rail TEST_VASP = new Rail("TEST_VASP"); + + private static final List KNOWN_VALUES = List.of(EMPTY, INTERNAL, TRP, GTR, TRUST, VERIFYVASP, SYGNA, EMAIL, TEST_VASP); private Rail(String value) { super(value); diff --git a/src/main/java/me/didit/types/TravelRuleTransferDetail.java b/src/main/java/me/didit/types/TravelRuleTransferDetail.java index f7839ec..c65fbfd 100644 --- a/src/main/java/me/didit/types/TravelRuleTransferDetail.java +++ b/src/main/java/me/didit/types/TravelRuleTransferDetail.java @@ -85,7 +85,7 @@ public Optional direction() { } /** - * The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered a sandbox application's transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response. + * The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered the sandbox transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response. * * @return the value, or empty when the field is absent or null * @throws me.didit.errors.UnexpectedResponseException when the field has another type @@ -338,7 +338,7 @@ public Builder direction(TravelRuleTransferDetail.Direction direction) { } /** - * The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered a sandbox application's transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response. + * The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered the sandbox transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response. * * @param rail the value, or {@code null} to send JSON null * @return this builder @@ -680,7 +680,7 @@ public boolean isKnown() { } /** - * The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered a sandbox application's transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response. + * The rail the transfer was routed over, or null when no rail was selected (for example below the threshold, a self-hosted counterparty wallet, an after-deposit registration, or no reachable counterparty). INTERNAL means both sides are Didit applications; EMAIL means the counterparty was reached by an emailed pickup link. TEST_VASP means the Didit Test VASP answered the sandbox transfer. Over GTR, VERIFYVASP and SYGNA, Didit reads the counterparty's answer from the network's response or by polling it every 5 minutes. TRUST only sends, so a TRUST transfer stays AWAITING_COUNTERPARTY until it expires. A network rail is used only when you have connected your own membership for that network. It is chosen after the transaction create returns, so it is null in that response. * *

An open enum: {@link #of(String)} accepts values this SDK version does not know yet. */ diff --git a/src/main/java/me/didit/types/WebhookEventPayload.java b/src/main/java/me/didit/types/WebhookEventPayload.java index dfcc11c..28804bc 100644 --- a/src/main/java/me/didit/types/WebhookEventPayload.java +++ b/src/main/java/me/didit/types/WebhookEventPayload.java @@ -331,7 +331,7 @@ public static WebhookEventPayload ofTravelRuleStatusUpdatedEvent(TravelRuleStatu /** * Whether this value is a {@code TravelRuleStatusUpdatedEvent}. * - * A Travel Rule exchange changed status. Sent on every transition up to and including FINISHED, CANCELLED or EXPIRED, never after. Sent for live applications only. There is no top-level status. + * A Travel Rule exchange changed status. Sent on every transition up to and including FINISHED, CANCELLED or EXPIRED, never after. Sent for live applications and, for Travel Rule exchanges, for sandbox applications too (environment: sandbox). There is no top-level status. * * @return true when it matches */