From 524243a641cfb439443592613422465cefd1f8d3 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 18 Sep 2026 15:48:54 +0000
Subject: [PATCH 1/2] feat(api): manual updates
---
.stats.yml | 6 +-
api.md | 82 ++-
src/index.ts | 46 +-
src/resources/index.ts | 10 +-
src/resources/intel.ts | 3 +
src/resources/intel/index.ts | 4 +
src/resources/intel/intel.ts | 15 +
src/resources/intel/kyc.ts | 190 +++++
src/resources/notify.ts | 87 +++
src/resources/shared.ts | 87 +++
src/resources/verification-management.ts | 230 +-----
.../verification-management/index.ts | 20 +
.../verification-management/sandbox.ts | 144 ++++
.../verification-management.ts | 251 +++++++
src/resources/verification.ts | 558 +-------------
src/resources/verification/index.ts | 10 +
src/resources/verification/phone.ts | 3 +
src/resources/verification/phone/history.ts | 681 ++++++++++++++++++
src/resources/verification/phone/index.ts | 12 +
src/resources/verification/phone/phone.ts | 31 +
src/resources/verification/verification.ts | 465 ++++++++++++
src/resources/watch.ts | 321 +++++----
tests/api-resources/intel/kyc.test.ts | 22 +
tests/api-resources/notify.test.ts | 25 +
.../verification-management/sandbox.test.ts | 70 ++
.../verification-management.test.ts | 0
.../verification/phone/history.test.ts | 72 ++
.../{ => verification}/verification.test.ts | 0
tests/api-resources/watch.test.ts | 36 +
29 files changed, 2539 insertions(+), 942 deletions(-)
create mode 100644 src/resources/intel.ts
create mode 100644 src/resources/intel/index.ts
create mode 100644 src/resources/intel/intel.ts
create mode 100644 src/resources/intel/kyc.ts
create mode 100644 src/resources/shared.ts
create mode 100644 src/resources/verification-management/index.ts
create mode 100644 src/resources/verification-management/sandbox.ts
create mode 100644 src/resources/verification-management/verification-management.ts
create mode 100644 src/resources/verification/index.ts
create mode 100644 src/resources/verification/phone.ts
create mode 100644 src/resources/verification/phone/history.ts
create mode 100644 src/resources/verification/phone/index.ts
create mode 100644 src/resources/verification/phone/phone.ts
create mode 100644 src/resources/verification/verification.ts
create mode 100644 tests/api-resources/intel/kyc.test.ts
create mode 100644 tests/api-resources/verification-management/sandbox.test.ts
rename tests/api-resources/{ => verification-management}/verification-management.test.ts (100%)
create mode 100644 tests/api-resources/verification/phone/history.test.ts
rename tests/api-resources/{ => verification}/verification.test.ts (100%)
diff --git a/.stats.yml b/.stats.yml
index b57e87a..cce5f55 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,4 +1,4 @@
-configured_endpoints: 19
-openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/prelude/prelude-86fc45f417e6468f6a6087f9e35b264b0a350e31385bc078a2027a1f1abd1d15.yml
+configured_endpoints: 27
+openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/prelude/prelude-33b70f86404b99046db5c61d3142b149dd7dec7eefe5e62ff3b397c7274aa5dc.yml
openapi_spec_hash: fb72aba38ec55a3b6b5162c9f5b4228d
-config_hash: 3dbe79c14ecd9a153418249f9155d159
+config_hash: 707d65d2f456a2b5ba5b2c565b60128a
diff --git a/api.md b/api.md
index b163185..fb13e1e 100644
--- a/api.md
+++ b/api.md
@@ -1,3 +1,10 @@
+# Shared
+
+Types:
+
+- Signals
+- Target
+
# Lookup
Types:
@@ -17,6 +24,7 @@ Types:
- NotifyListSubscriptionConfigsResponse
- NotifyListSubscriptionPhoneNumberEventsResponse
- NotifyListSubscriptionPhoneNumbersResponse
+- NotifyReplyResponse
- NotifySendResponse
- NotifySendBatchResponse
@@ -27,6 +35,7 @@ Methods:
- client.notify.listSubscriptionConfigs({ ...params }) -> NotifyListSubscriptionConfigsResponse
- client.notify.listSubscriptionPhoneNumberEvents(configId, phoneNumber, { ...params }) -> NotifyListSubscriptionPhoneNumberEventsResponse
- client.notify.listSubscriptionPhoneNumbers(configId, { ...params }) -> NotifyListSubscriptionPhoneNumbersResponse
+- client.notify.reply({ ...params }) -> NotifyReplyResponse
- client.notify.send({ ...params }) -> NotifySendResponse
- client.notify.sendBatch({ ...params }) -> NotifySendBatchResponse
@@ -44,42 +53,87 @@ Methods:
Types:
-- VerificationCreateResponse
-- VerificationCheckResponse
+- VerificationCreateResponse
+- VerificationCheckResponse
+
+Methods:
+
+- client.verification.create({ ...params }) -> VerificationCreateResponse
+- client.verification.check({ ...params }) -> VerificationCheckResponse
+
+## Phone
+
+### History
+
+Types:
+
+- PhoneVerificationCarrier
+- PhoneVerificationMoney
+- PhoneVerificationPsd2Transaction
+- HistoryRetrieveResponse
+- HistoryListResponse
Methods:
-- client.verification.create({ ...params }) -> VerificationCreateResponse
-- client.verification.check({ ...params }) -> VerificationCheckResponse
+- client.verification.phone.history.retrieve(id) -> HistoryRetrieveResponse
+- client.verification.phone.history.list({ ...params }) -> HistoryListResponse
# VerificationManagement
Types:
-- VerificationManagementDeletePhoneNumberResponse
-- VerificationManagementListPhoneNumbersResponse
-- VerificationManagementListSenderIDsResponse
-- VerificationManagementSetPhoneNumberResponse
-- VerificationManagementSubmitSenderIDResponse
+- VerificationManagementDeletePhoneNumberResponse
+- VerificationManagementListPhoneNumbersResponse
+- VerificationManagementListSenderIDsResponse
+- VerificationManagementSetPhoneNumberResponse
+- VerificationManagementSubmitSenderIDResponse
Methods:
-- client.verificationManagement.deletePhoneNumber(action, { ...params }) -> VerificationManagementDeletePhoneNumberResponse
-- client.verificationManagement.listPhoneNumbers(action) -> VerificationManagementListPhoneNumbersResponse
-- client.verificationManagement.listSenderIds() -> VerificationManagementListSenderIDsResponse
-- client.verificationManagement.setPhoneNumber(action, { ...params }) -> VerificationManagementSetPhoneNumberResponse
-- client.verificationManagement.submitSenderId({ ...params }) -> VerificationManagementSubmitSenderIDResponse
+- client.verificationManagement.deletePhoneNumber(action, { ...params }) -> VerificationManagementDeletePhoneNumberResponse
+- client.verificationManagement.listPhoneNumbers(action) -> VerificationManagementListPhoneNumbersResponse
+- client.verificationManagement.listSenderIds() -> VerificationManagementListSenderIDsResponse
+- client.verificationManagement.setPhoneNumber(action, { ...params }) -> VerificationManagementSetPhoneNumberResponse
+- client.verificationManagement.submitSenderId({ ...params }) -> VerificationManagementSubmitSenderIDResponse
+
+## Sandbox
+
+Types:
+
+- SandboxAddPhoneNumberResponse
+- SandboxDeletePhoneNumberResponse
+- SandboxListPhoneNumbersResponse
+
+Methods:
+
+- client.verificationManagement.sandbox.addPhoneNumber({ ...params }) -> SandboxAddPhoneNumberResponse
+- client.verificationManagement.sandbox.deletePhoneNumber(phoneNumber) -> SandboxDeletePhoneNumberResponse
+- client.verificationManagement.sandbox.listPhoneNumbers() -> SandboxListPhoneNumbersResponse
# Watch
Types:
+- WatchEvaluateResponse
- WatchPredictResponse
- WatchSendEventsResponse
- WatchSendFeedbacksResponse
Methods:
+- client.watch.evaluate({ ...params }) -> WatchEvaluateResponse
- client.watch.predict({ ...params }) -> WatchPredictResponse
- client.watch.sendEvents({ ...params }) -> WatchSendEventsResponse
- client.watch.sendFeedbacks({ ...params }) -> WatchSendFeedbacksResponse
+
+# Intel
+
+## KYC
+
+Types:
+
+- KYCMatchResponse
+
+Methods:
+
+- client.intel.kyc.match(phone, { ...params }) -> KYCMatchResponse
diff --git a/src/index.ts b/src/index.ts
index fc7dcd6..e0776c3 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -17,6 +17,8 @@ import {
NotifyListSubscriptionPhoneNumberEventsResponse,
NotifyListSubscriptionPhoneNumbersParams,
NotifyListSubscriptionPhoneNumbersResponse,
+ NotifyReplyParams,
+ NotifyReplyResponse,
NotifySendBatchParams,
NotifySendBatchResponse,
NotifySendParams,
@@ -24,12 +26,17 @@ import {
} from './resources/notify';
import { Transactional, TransactionalSendParams, TransactionalSendResponse } from './resources/transactional';
import {
- Verification,
- VerificationCheckParams,
- VerificationCheckResponse,
- VerificationCreateParams,
- VerificationCreateResponse,
-} from './resources/verification';
+ Watch,
+ WatchEvaluateParams,
+ WatchEvaluateResponse,
+ WatchPredictParams,
+ WatchPredictResponse,
+ WatchSendEventsParams,
+ WatchSendEventsResponse,
+ WatchSendFeedbacksParams,
+ WatchSendFeedbacksResponse,
+} from './resources/watch';
+import { Intel } from './resources/intel/intel';
import {
VerificationManagement,
VerificationManagementDeletePhoneNumberParams,
@@ -40,16 +47,14 @@ import {
VerificationManagementSetPhoneNumberResponse,
VerificationManagementSubmitSenderIDParams,
VerificationManagementSubmitSenderIDResponse,
-} from './resources/verification-management';
+} from './resources/verification-management/verification-management';
import {
- Watch,
- WatchPredictParams,
- WatchPredictResponse,
- WatchSendEventsParams,
- WatchSendEventsResponse,
- WatchSendFeedbacksParams,
- WatchSendFeedbacksResponse,
-} from './resources/watch';
+ Verification,
+ VerificationCheckParams,
+ VerificationCheckResponse,
+ VerificationCreateParams,
+ VerificationCreateResponse,
+} from './resources/verification/verification';
export interface ClientOptions {
/**
@@ -203,6 +208,7 @@ export class Prelude extends Core.APIClient {
* Evaluate email addresses and phone numbers for trustworthiness.
*/
watch: API.Watch = new API.Watch(this);
+ intel: API.Intel = new API.Intel(this);
/**
* Check whether the base URL is set to its default.
@@ -257,6 +263,7 @@ Prelude.Transactional = Transactional;
Prelude.Verification = Verification;
Prelude.VerificationManagement = VerificationManagement;
Prelude.Watch = Watch;
+Prelude.Intel = Intel;
export declare namespace Prelude {
export type RequestOptions = Core.RequestOptions;
@@ -274,11 +281,13 @@ export declare namespace Prelude {
type NotifyListSubscriptionConfigsResponse as NotifyListSubscriptionConfigsResponse,
type NotifyListSubscriptionPhoneNumberEventsResponse as NotifyListSubscriptionPhoneNumberEventsResponse,
type NotifyListSubscriptionPhoneNumbersResponse as NotifyListSubscriptionPhoneNumbersResponse,
+ type NotifyReplyResponse as NotifyReplyResponse,
type NotifySendResponse as NotifySendResponse,
type NotifySendBatchResponse as NotifySendBatchResponse,
type NotifyListSubscriptionConfigsParams as NotifyListSubscriptionConfigsParams,
type NotifyListSubscriptionPhoneNumberEventsParams as NotifyListSubscriptionPhoneNumberEventsParams,
type NotifyListSubscriptionPhoneNumbersParams as NotifyListSubscriptionPhoneNumbersParams,
+ type NotifyReplyParams as NotifyReplyParams,
type NotifySendParams as NotifySendParams,
type NotifySendBatchParams as NotifySendBatchParams,
};
@@ -311,13 +320,20 @@ export declare namespace Prelude {
export {
Watch as Watch,
+ type WatchEvaluateResponse as WatchEvaluateResponse,
type WatchPredictResponse as WatchPredictResponse,
type WatchSendEventsResponse as WatchSendEventsResponse,
type WatchSendFeedbacksResponse as WatchSendFeedbacksResponse,
+ type WatchEvaluateParams as WatchEvaluateParams,
type WatchPredictParams as WatchPredictParams,
type WatchSendEventsParams as WatchSendEventsParams,
type WatchSendFeedbacksParams as WatchSendFeedbacksParams,
};
+
+ export { Intel as Intel };
+
+ export type Signals = API.Signals;
+ export type Target = API.Target;
}
export { toFile, fileFromPath } from './uploads';
diff --git a/src/resources/index.ts b/src/resources/index.ts
index 44dec0d..b35034a 100644
--- a/src/resources/index.ts
+++ b/src/resources/index.ts
@@ -1,5 +1,7 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+export * from './shared';
+export { Intel } from './intel/intel';
export { Lookup, type LookupLookupResponse, type LookupLookupParams } from './lookup';
export {
Notify,
@@ -8,11 +10,13 @@ export {
type NotifyListSubscriptionConfigsResponse,
type NotifyListSubscriptionPhoneNumberEventsResponse,
type NotifyListSubscriptionPhoneNumbersResponse,
+ type NotifyReplyResponse,
type NotifySendResponse,
type NotifySendBatchResponse,
type NotifyListSubscriptionConfigsParams,
type NotifyListSubscriptionPhoneNumberEventsParams,
type NotifyListSubscriptionPhoneNumbersParams,
+ type NotifyReplyParams,
type NotifySendParams,
type NotifySendBatchParams,
} from './notify';
@@ -23,7 +27,7 @@ export {
type VerificationCheckResponse,
type VerificationCreateParams,
type VerificationCheckParams,
-} from './verification';
+} from './verification/verification';
export {
VerificationManagement,
type VerificationManagementDeletePhoneNumberResponse,
@@ -34,12 +38,14 @@ export {
type VerificationManagementDeletePhoneNumberParams,
type VerificationManagementSetPhoneNumberParams,
type VerificationManagementSubmitSenderIDParams,
-} from './verification-management';
+} from './verification-management/verification-management';
export {
Watch,
+ type WatchEvaluateResponse,
type WatchPredictResponse,
type WatchSendEventsResponse,
type WatchSendFeedbacksResponse,
+ type WatchEvaluateParams,
type WatchPredictParams,
type WatchSendEventsParams,
type WatchSendFeedbacksParams,
diff --git a/src/resources/intel.ts b/src/resources/intel.ts
new file mode 100644
index 0000000..409016b
--- /dev/null
+++ b/src/resources/intel.ts
@@ -0,0 +1,3 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export * from './intel/index';
diff --git a/src/resources/intel/index.ts b/src/resources/intel/index.ts
new file mode 100644
index 0000000..9aae2ed
--- /dev/null
+++ b/src/resources/intel/index.ts
@@ -0,0 +1,4 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export { Intel } from './intel';
+export { KYC, type KYCMatchResponse, type KYCMatchParams } from './kyc';
diff --git a/src/resources/intel/intel.ts b/src/resources/intel/intel.ts
new file mode 100644
index 0000000..3160268
--- /dev/null
+++ b/src/resources/intel/intel.ts
@@ -0,0 +1,15 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../resource';
+import * as KYCAPI from './kyc';
+import { KYC, KYCMatchParams, KYCMatchResponse } from './kyc';
+
+export class Intel extends APIResource {
+ kyc: KYCAPI.KYC = new KYCAPI.KYC(this._client);
+}
+
+Intel.KYC = KYC;
+
+export declare namespace Intel {
+ export { KYC as KYC, type KYCMatchResponse as KYCMatchResponse, type KYCMatchParams as KYCMatchParams };
+}
diff --git a/src/resources/intel/kyc.ts b/src/resources/intel/kyc.ts
new file mode 100644
index 0000000..209d23b
--- /dev/null
+++ b/src/resources/intel/kyc.ts
@@ -0,0 +1,190 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../resource';
+import * as Core from '../../core';
+
+/**
+ * Retrieve detailed information about a phone number including carrier data, line type, and portability status.
+ */
+export class KYC extends APIResource {
+ /**
+ * Verify identity attributes against the subscriber record held by the end-user's
+ * mobile operator. Send a phone number along with the attributes to check; Prelude
+ * resolves the operator internally and returns a per-attribute match. Currently
+ * available for France only (Orange, SFR, Bouygues) and must be enabled for your
+ * account.
+ *
+ * @example
+ * ```ts
+ * const response = await client.intel.kyc.match(
+ * '+12065550100',
+ * );
+ * ```
+ */
+ match(
+ phone: string,
+ body: KYCMatchParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.post(`/v2/intel/kyc/match/${phone}`, { body, ...options });
+ }
+}
+
+/**
+ * The per-attribute match result. Each `_match` field is one of `true`,
+ * `false`, or `not_available` (the operator could not answer for that attribute).
+ * Fuzzy attributes additionally return a `_match_score` (0-99
+ * similarity) when they do not match exactly; the score is omitted on a match or
+ * when `not_available`.
+ */
+export interface KYCMatchResponse {
+ /**
+ * Whether the street address matched the operator's record.
+ */
+ address_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Similarity score (0-99) for the address. Returned only on a non-match.
+ */
+ address_match_score?: number;
+
+ /**
+ * Whether the date of birth matched the operator's record. Compared exactly; never
+ * scored.
+ */
+ birthdate_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * The country code of the phone number.
+ */
+ country_code?: string;
+
+ /**
+ * Whether the country matched the operator's record. Compared exactly; never
+ * scored.
+ */
+ country_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Whether the email address matched the operator's record.
+ */
+ email_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Similarity score (0-99) for the email. Returned only on a non-match.
+ */
+ email_match_score?: number;
+
+ /**
+ * Whether the family name matched the operator's record.
+ */
+ family_name_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Similarity score (0-99) for the family name. Returned only on a non-match.
+ */
+ family_name_match_score?: number;
+
+ /**
+ * Whether the given name matched the operator's record.
+ */
+ given_name_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Similarity score (0-99) for the given name. Returned only on a non-match.
+ */
+ given_name_match_score?: number;
+
+ /**
+ * Whether the locality matched the operator's record.
+ */
+ locality_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Similarity score (0-99) for the locality. Returned only on a non-match.
+ */
+ locality_match_score?: number;
+
+ /**
+ * The mobile operator that answered the match.
+ */
+ operator?: string;
+
+ /**
+ * The phone number that was matched, in E.164 format.
+ */
+ phone_number?: string;
+
+ /**
+ * Whether the postal code matched the operator's record. Compared exactly; never
+ * scored.
+ */
+ postal_code_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Whether the region matched the operator's record.
+ */
+ region_match?: 'true' | 'false' | 'not_available';
+
+ /**
+ * Similarity score (0-99) for the region. Returned only on a non-match.
+ */
+ region_match_score?: number;
+
+ /**
+ * A string that identifies this specific request. Report it back to us to help us
+ * diagnose your issues.
+ */
+ request_id?: string;
+}
+
+export interface KYCMatchParams {
+ /**
+ * The street address.
+ */
+ address?: string;
+
+ /**
+ * The date of birth in ISO 8601 (`YYYY-MM-DD`) format. Compared exactly.
+ */
+ birthdate?: string;
+
+ /**
+ * The ISO 3166-1 alpha-2 country code. Compared exactly.
+ */
+ country?: string;
+
+ /**
+ * The email address.
+ */
+ email?: string;
+
+ /**
+ * The end-user's family (last) name.
+ */
+ family_name?: string;
+
+ /**
+ * The end-user's given (first) name.
+ */
+ given_name?: string;
+
+ /**
+ * The locality (city).
+ */
+ locality?: string;
+
+ /**
+ * The postal code. Compared exactly.
+ */
+ postal_code?: string;
+
+ /**
+ * The region, state, or province.
+ */
+ region?: string;
+}
+
+export declare namespace KYC {
+ export { type KYCMatchResponse as KYCMatchResponse, type KYCMatchParams as KYCMatchParams };
+}
diff --git a/src/resources/notify.ts b/src/resources/notify.ts
index a538590..5979120 100644
--- a/src/resources/notify.ts
+++ b/src/resources/notify.ts
@@ -167,6 +167,24 @@ export class Notify extends APIResource {
});
}
+ /**
+ * Send a free-form text reply to an inbound WhatsApp message within the 24-hour
+ * conversation window. See
+ * [WhatsApp 2-Way Messaging](/notify/v2/documentation/whatsapp) for details.
+ *
+ * @example
+ * ```ts
+ * const response = await client.notify.reply({
+ * reply_to: 'im_01k8aq2zggeyssvt53zgvpx63a',
+ * text: "Thanks for reaching out! We'll look into your request.",
+ * to: '+33612345678',
+ * });
+ * ```
+ */
+ reply(body: NotifyReplyParams, options?: Core.RequestOptions): Core.APIPromise {
+ return this._client.post('/v2/notify/reply', { body, ...options });
+ }
+
/**
* Send transactional and marketing messages to your users via SMS, RCS and
* WhatsApp with automatic compliance enforcement.
@@ -511,6 +529,43 @@ export namespace NotifyListSubscriptionPhoneNumbersResponse {
}
}
+export interface NotifyReplyResponse {
+ /**
+ * The reply message identifier.
+ */
+ id: string;
+
+ /**
+ * The reply creation date in RFC3339 format.
+ */
+ created_at: string;
+
+ /**
+ * The inbound message ID this reply was sent in response to.
+ */
+ reply_to: string;
+
+ /**
+ * The reply message body that was sent.
+ */
+ text: string;
+
+ /**
+ * The recipient's phone number in E.164 format.
+ */
+ to: string;
+
+ /**
+ * The callback URL where webhooks will be sent.
+ */
+ callback_url?: string;
+
+ /**
+ * The user-defined correlation identifier echoed back from the request.
+ */
+ correlation_id?: string;
+}
+
export interface NotifySendResponse {
/**
* The message identifier.
@@ -762,6 +817,36 @@ export interface NotifyListSubscriptionPhoneNumbersParams {
state?: 'SUB' | 'UNSUB';
}
+export interface NotifyReplyParams {
+ /**
+ * The inbound message ID (prefixed with `im_`) to reply to. This ID is provided in
+ * the `inbound.message.received` webhook event.
+ */
+ reply_to: string;
+
+ /**
+ * The reply message body sent as a free-form WhatsApp text.
+ */
+ text: string;
+
+ /**
+ * The recipient's phone number in E.164 format. Must match the phone number that
+ * sent the original inbound message.
+ */
+ to: string;
+
+ /**
+ * The URL where webhooks will be sent for delivery events of this reply.
+ */
+ callback_url?: string;
+
+ /**
+ * A user-defined identifier to correlate this reply with your internal systems. It
+ * is returned in the response and any webhook events that refer to this message.
+ */
+ correlation_id?: string;
+}
+
export interface NotifySendParams {
/**
* The template identifier configured by your Customer Success team.
@@ -988,11 +1073,13 @@ export declare namespace Notify {
type NotifyListSubscriptionConfigsResponse as NotifyListSubscriptionConfigsResponse,
type NotifyListSubscriptionPhoneNumberEventsResponse as NotifyListSubscriptionPhoneNumberEventsResponse,
type NotifyListSubscriptionPhoneNumbersResponse as NotifyListSubscriptionPhoneNumbersResponse,
+ type NotifyReplyResponse as NotifyReplyResponse,
type NotifySendResponse as NotifySendResponse,
type NotifySendBatchResponse as NotifySendBatchResponse,
type NotifyListSubscriptionConfigsParams as NotifyListSubscriptionConfigsParams,
type NotifyListSubscriptionPhoneNumberEventsParams as NotifyListSubscriptionPhoneNumberEventsParams,
type NotifyListSubscriptionPhoneNumbersParams as NotifyListSubscriptionPhoneNumbersParams,
+ type NotifyReplyParams as NotifyReplyParams,
type NotifySendParams as NotifySendParams,
type NotifySendBatchParams as NotifySendBatchParams,
};
diff --git a/src/resources/shared.ts b/src/resources/shared.ts
new file mode 100644
index 0000000..4eb0bef
--- /dev/null
+++ b/src/resources/shared.ts
@@ -0,0 +1,87 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+/**
+ * The signals used for anti-fraud. For more details, refer to
+ * [Signals](/verify/v2/documentation/prevent-fraud#signals).
+ */
+export interface Signals {
+ /**
+ * The version of your application.
+ */
+ app_version?: string;
+
+ /**
+ * A unique ID for the user's device. You should ensure that each user device has a
+ * unique `device_id` value. Ideally, for Android, this corresponds to the
+ * `ANDROID_ID` and for iOS, this corresponds to the `identifierForVendor`.
+ */
+ device_id?: string;
+
+ /**
+ * The model of the user's device.
+ */
+ device_model?: string;
+
+ /**
+ * The type of the user's device.
+ */
+ device_platform?: 'android' | 'ios' | 'ipados' | 'tvos' | 'web';
+
+ /**
+ * Whether the end-user already exists in your system, for example an existing
+ * account signing in again rather than a first-time signup. Unlike
+ * `is_trusted_user`, this signal does not bypass fraud checks; it is taken into
+ * account as one additional anti-fraud signal. For more details, refer to
+ * [Signals](/verify/v2/documentation/prevent-fraud#signals).
+ */
+ existing_user?: boolean;
+
+ /**
+ * The public IP v4 or v6 address of the end-user's device. You should collect this
+ * from your backend. If your backend is behind a proxy, use the `X-Forwarded-For`,
+ * `Forwarded`, `True-Client-IP`, `CF-Connecting-IP` or an equivalent header to get
+ * the actual public IP of the end-user's device.
+ */
+ ip?: string;
+
+ /**
+ * This signal should indicate a higher level of trust, explicitly stating that the
+ * user is genuine. Contact us to discuss your use case. For more details, refer to
+ * [Signals](/verify/v2/documentation/prevent-fraud#signals).
+ */
+ is_trusted_user?: boolean;
+
+ /**
+ * The JA4 fingerprint observed for the end-user's connection. Prelude will infer
+ * it automatically when you use our Frontend SDKs (which use Prelude's edge
+ * network), but you can also forward the value if you terminate TLS yourself.
+ */
+ ja4_fingerprint?: string;
+
+ /**
+ * The version of the user's device operating system.
+ */
+ os_version?: string;
+
+ /**
+ * The user agent of the user's device. If the individual fields (os_version,
+ * device_platform, device_model) are provided, we will prioritize those values
+ * instead of parsing them from the user agent string.
+ */
+ user_agent?: string;
+}
+
+/**
+ * The operation target. Either a phone number or an email address.
+ */
+export interface Target {
+ /**
+ * The type of the target. Either "phone_number" or "email_address".
+ */
+ type: 'phone_number' | 'email_address';
+
+ /**
+ * An E.164 formatted phone number or an email address.
+ */
+ value: string;
+}
diff --git a/src/resources/verification-management.ts b/src/resources/verification-management.ts
index fabae00..eb77d9f 100644
--- a/src/resources/verification-management.ts
+++ b/src/resources/verification-management.ts
@@ -1,231 +1,3 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-import { APIResource } from '../resource';
-import * as Core from '../core';
-
-/**
- * Verify phone numbers.
- */
-export class VerificationManagement extends APIResource {
- /**
- * Remove a phone number from the allow or block list.
- *
- * This operation is idempotent - re-deleting the same phone number will not result
- * in errors. If the phone number does not exist in the specified list, the
- * operation will succeed without making any changes.
- *
- * In order to get access to this endpoint, contact our support team.
- *
- * @example
- * ```ts
- * const response =
- * await client.verificationManagement.deletePhoneNumber(
- * 'allow',
- * { phone_number: '+30123456789' },
- * );
- * ```
- */
- deletePhoneNumber(
- action: 'allow' | 'block',
- body: VerificationManagementDeletePhoneNumberParams,
- options?: Core.RequestOptions,
- ): Core.APIPromise {
- return this._client.delete(`/v2/verification/management/phone-numbers/${action}`, { body, ...options });
- }
-
- /**
- * Retrieve the list of phone numbers in the allow or block list.
- *
- * In order to get access to this endpoint, contact our support team.
- *
- * @example
- * ```ts
- * const response =
- * await client.verificationManagement.listPhoneNumbers(
- * 'allow',
- * );
- * ```
- */
- listPhoneNumbers(
- action: 'allow' | 'block',
- options?: Core.RequestOptions,
- ): Core.APIPromise {
- return this._client.get(`/v2/verification/management/phone-numbers/${action}`, options);
- }
-
- /**
- * Retrieve sender IDs list.
- *
- * In order to get access to this endpoint, contact our support team.
- *
- * @example
- * ```ts
- * const response =
- * await client.verificationManagement.listSenderIds();
- * ```
- */
- listSenderIds(options?: Core.RequestOptions): Core.APIPromise {
- return this._client.get('/v2/verification/management/sender-id', options);
- }
-
- /**
- * Add a phone number to the allow or block list.
- *
- * This operation is idempotent - re-adding the same phone number will not result
- * in duplicate entries or errors. If the phone number already exists in the
- * specified list, the operation will succeed without making any changes.
- *
- * In order to get access to this endpoint, contact our support team.
- *
- * @example
- * ```ts
- * const response =
- * await client.verificationManagement.setPhoneNumber(
- * 'allow',
- * { phone_number: '+30123456789' },
- * );
- * ```
- */
- setPhoneNumber(
- action: 'allow' | 'block',
- body: VerificationManagementSetPhoneNumberParams,
- options?: Core.RequestOptions,
- ): Core.APIPromise {
- return this._client.post(`/v2/verification/management/phone-numbers/${action}`, { body, ...options });
- }
-
- /**
- * This endpoint allows you to submit a new sender ID for verification purposes.
- *
- * In order to get access to this endpoint, contact our support team.
- *
- * @example
- * ```ts
- * const response =
- * await client.verificationManagement.submitSenderId({
- * sender_id: 'Prelude',
- * });
- * ```
- */
- submitSenderId(
- body: VerificationManagementSubmitSenderIDParams,
- options?: Core.RequestOptions,
- ): Core.APIPromise {
- return this._client.post('/v2/verification/management/sender-id', { body, ...options });
- }
-}
-
-export interface VerificationManagementDeletePhoneNumberResponse {
- /**
- * The E.164 formatted phone number that was removed from the list.
- */
- phone_number: string;
-}
-
-export interface VerificationManagementListPhoneNumbersResponse {
- /**
- * A list of phone numbers in the allow or block list.
- */
- phone_numbers: Array;
-}
-
-export namespace VerificationManagementListPhoneNumbersResponse {
- export interface PhoneNumber {
- /**
- * The date and time when the phone number was added to the list.
- */
- created_at: string;
-
- /**
- * An E.164 formatted phone number.
- */
- phone_number: string;
- }
-}
-
-/**
- * A list of Sender ID.
- */
-export interface VerificationManagementListSenderIDsResponse {
- sender_ids?: Array;
-}
-
-export namespace VerificationManagementListSenderIDsResponse {
- export interface SenderID {
- /**
- * Value that will be presented as Sender ID
- */
- sender_id?: string;
-
- /**
- * It indicates the status of the Sender ID. Possible values are:
- *
- * - `approved` - The Sender ID is approved.
- * - `pending` - The Sender ID is pending.
- * - `rejected` - The Sender ID is rejected.
- */
- status?: 'approved' | 'pending' | 'rejected';
- }
-}
-
-export interface VerificationManagementSetPhoneNumberResponse {
- /**
- * The E.164 formatted phone number that was added to the list.
- */
- phone_number: string;
-}
-
-export interface VerificationManagementSubmitSenderIDResponse {
- /**
- * The sender ID that was added.
- */
- sender_id: string;
-
- /**
- * It indicates the status of the sender ID. Possible values are:
- *
- * - `approved` - The sender ID is approved.
- * - `pending` - The sender ID is pending.
- * - `rejected` - The sender ID is rejected.
- */
- status: 'approved' | 'pending' | 'rejected';
-
- /**
- * The reason why the sender ID was rejected.
- */
- reason?: string;
-}
-
-export interface VerificationManagementDeletePhoneNumberParams {
- /**
- * An E.164 formatted phone number to remove from the list.
- */
- phone_number: string;
-}
-
-export interface VerificationManagementSetPhoneNumberParams {
- /**
- * An E.164 formatted phone number to add to the list.
- */
- phone_number: string;
-}
-
-export interface VerificationManagementSubmitSenderIDParams {
- /**
- * The sender ID to add.
- */
- sender_id: string;
-}
-
-export declare namespace VerificationManagement {
- export {
- type VerificationManagementDeletePhoneNumberResponse as VerificationManagementDeletePhoneNumberResponse,
- type VerificationManagementListPhoneNumbersResponse as VerificationManagementListPhoneNumbersResponse,
- type VerificationManagementListSenderIDsResponse as VerificationManagementListSenderIDsResponse,
- type VerificationManagementSetPhoneNumberResponse as VerificationManagementSetPhoneNumberResponse,
- type VerificationManagementSubmitSenderIDResponse as VerificationManagementSubmitSenderIDResponse,
- type VerificationManagementDeletePhoneNumberParams as VerificationManagementDeletePhoneNumberParams,
- type VerificationManagementSetPhoneNumberParams as VerificationManagementSetPhoneNumberParams,
- type VerificationManagementSubmitSenderIDParams as VerificationManagementSubmitSenderIDParams,
- };
-}
+export * from './verification-management/index';
diff --git a/src/resources/verification-management/index.ts b/src/resources/verification-management/index.ts
new file mode 100644
index 0000000..37b8604
--- /dev/null
+++ b/src/resources/verification-management/index.ts
@@ -0,0 +1,20 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export {
+ Sandbox,
+ type SandboxAddPhoneNumberResponse,
+ type SandboxDeletePhoneNumberResponse,
+ type SandboxListPhoneNumbersResponse,
+ type SandboxAddPhoneNumberParams,
+} from './sandbox';
+export {
+ VerificationManagement,
+ type VerificationManagementDeletePhoneNumberResponse,
+ type VerificationManagementListPhoneNumbersResponse,
+ type VerificationManagementListSenderIDsResponse,
+ type VerificationManagementSetPhoneNumberResponse,
+ type VerificationManagementSubmitSenderIDResponse,
+ type VerificationManagementDeletePhoneNumberParams,
+ type VerificationManagementSetPhoneNumberParams,
+ type VerificationManagementSubmitSenderIDParams,
+} from './verification-management';
diff --git a/src/resources/verification-management/sandbox.ts b/src/resources/verification-management/sandbox.ts
new file mode 100644
index 0000000..f3f47f7
--- /dev/null
+++ b/src/resources/verification-management/sandbox.ts
@@ -0,0 +1,144 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../resource';
+import * as Core from '../../core';
+
+/**
+ * Verify phone numbers.
+ */
+export class Sandbox extends APIResource {
+ /**
+ * Register a phone number as a sandbox number and associate it with a fixed
+ * attempt code. Subsequent verification attempts against this number will not
+ * trigger a real SMS/call and will validate against the configured attempt code.
+ *
+ * This operation is idempotent - re-adding the same phone number will overwrite
+ * the existing attempt code.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.sandbox.addPhoneNumber(
+ * {
+ * attempt_code: '123456',
+ * phone_number: '+30123456789',
+ * },
+ * );
+ * ```
+ */
+ addPhoneNumber(
+ body: SandboxAddPhoneNumberParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.put('/v2/verification/management/phone-numbers/sandbox', { body, ...options });
+ }
+
+ /**
+ * Remove a phone number from the sandbox list.
+ *
+ * This operation is idempotent - deleting a phone number that is not in the
+ * sandbox list will succeed without making any changes.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.sandbox.deletePhoneNumber(
+ * '+12065550100',
+ * );
+ * ```
+ */
+ deletePhoneNumber(
+ phoneNumber: string,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.delete(`/v2/verification/management/phone-numbers/sandbox/${phoneNumber}`, options);
+ }
+
+ /**
+ * Retrieve the list of sandbox phone numbers for the account. Sandbox numbers are
+ * test numbers that bypass the real verification flow and return a fixed attempt
+ * code.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.sandbox.listPhoneNumbers();
+ * ```
+ */
+ listPhoneNumbers(options?: Core.RequestOptions): Core.APIPromise {
+ return this._client.get('/v2/verification/management/phone-numbers/sandbox', options);
+ }
+}
+
+export interface SandboxAddPhoneNumberResponse {
+ /**
+ * The fixed attempt code associated with the sandbox phone number.
+ */
+ attempt_code: string;
+
+ /**
+ * The E.164 formatted phone number that was added to the sandbox list.
+ */
+ phone_number: string;
+}
+
+export interface SandboxDeletePhoneNumberResponse {
+ /**
+ * The E.164 formatted phone number that was removed from the sandbox list.
+ */
+ phone_number: string;
+}
+
+export interface SandboxListPhoneNumbersResponse {
+ /**
+ * A list of sandbox phone numbers.
+ */
+ phone_numbers: Array;
+}
+
+export namespace SandboxListPhoneNumbersResponse {
+ export interface PhoneNumber {
+ /**
+ * The fixed attempt code associated with the sandbox phone number.
+ */
+ attempt_code: string;
+
+ /**
+ * The date and time when the phone number was added to the sandbox list.
+ */
+ created_at: string;
+
+ /**
+ * An E.164 formatted phone number.
+ */
+ phone_number: string;
+ }
+}
+
+export interface SandboxAddPhoneNumberParams {
+ /**
+ * The fixed attempt code that will validate verification attempts for this phone
+ * number.
+ */
+ attempt_code: string;
+
+ /**
+ * An E.164 formatted phone number to add to the sandbox list.
+ */
+ phone_number: string;
+}
+
+export declare namespace Sandbox {
+ export {
+ type SandboxAddPhoneNumberResponse as SandboxAddPhoneNumberResponse,
+ type SandboxDeletePhoneNumberResponse as SandboxDeletePhoneNumberResponse,
+ type SandboxListPhoneNumbersResponse as SandboxListPhoneNumbersResponse,
+ type SandboxAddPhoneNumberParams as SandboxAddPhoneNumberParams,
+ };
+}
diff --git a/src/resources/verification-management/verification-management.ts b/src/resources/verification-management/verification-management.ts
new file mode 100644
index 0000000..f005d18
--- /dev/null
+++ b/src/resources/verification-management/verification-management.ts
@@ -0,0 +1,251 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../resource';
+import * as Core from '../../core';
+import * as SandboxAPI from './sandbox';
+import {
+ Sandbox,
+ SandboxAddPhoneNumberParams,
+ SandboxAddPhoneNumberResponse,
+ SandboxDeletePhoneNumberResponse,
+ SandboxListPhoneNumbersResponse,
+} from './sandbox';
+
+/**
+ * Verify phone numbers.
+ */
+export class VerificationManagement extends APIResource {
+ sandbox: SandboxAPI.Sandbox = new SandboxAPI.Sandbox(this._client);
+
+ /**
+ * Remove a phone number from the allow or block list.
+ *
+ * This operation is idempotent - re-deleting the same phone number will not result
+ * in errors. If the phone number does not exist in the specified list, the
+ * operation will succeed without making any changes.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.deletePhoneNumber(
+ * 'allow',
+ * { phone_number: '+30123456789' },
+ * );
+ * ```
+ */
+ deletePhoneNumber(
+ action: 'allow' | 'block',
+ body: VerificationManagementDeletePhoneNumberParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.delete(`/v2/verification/management/phone-numbers/${action}`, { body, ...options });
+ }
+
+ /**
+ * Retrieve the list of phone numbers in the allow or block list.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.listPhoneNumbers(
+ * 'allow',
+ * );
+ * ```
+ */
+ listPhoneNumbers(
+ action: 'allow' | 'block',
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.get(`/v2/verification/management/phone-numbers/${action}`, options);
+ }
+
+ /**
+ * Retrieve sender IDs list.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.listSenderIds();
+ * ```
+ */
+ listSenderIds(options?: Core.RequestOptions): Core.APIPromise {
+ return this._client.get('/v2/verification/management/sender-id', options);
+ }
+
+ /**
+ * Add a phone number to the allow or block list.
+ *
+ * This operation is idempotent - re-adding the same phone number will not result
+ * in duplicate entries or errors. If the phone number already exists in the
+ * specified list, the operation will succeed without making any changes.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.setPhoneNumber(
+ * 'allow',
+ * { phone_number: '+30123456789' },
+ * );
+ * ```
+ */
+ setPhoneNumber(
+ action: 'allow' | 'block',
+ body: VerificationManagementSetPhoneNumberParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.post(`/v2/verification/management/phone-numbers/${action}`, { body, ...options });
+ }
+
+ /**
+ * This endpoint allows you to submit a new sender ID for verification purposes.
+ *
+ * In order to get access to this endpoint, contact our support team.
+ *
+ * @example
+ * ```ts
+ * const response =
+ * await client.verificationManagement.submitSenderId({
+ * sender_id: 'Prelude',
+ * });
+ * ```
+ */
+ submitSenderId(
+ body: VerificationManagementSubmitSenderIDParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.post('/v2/verification/management/sender-id', { body, ...options });
+ }
+}
+
+export interface VerificationManagementDeletePhoneNumberResponse {
+ /**
+ * The E.164 formatted phone number that was removed from the list.
+ */
+ phone_number: string;
+}
+
+export interface VerificationManagementListPhoneNumbersResponse {
+ /**
+ * A list of phone numbers in the allow or block list.
+ */
+ phone_numbers: Array;
+}
+
+export namespace VerificationManagementListPhoneNumbersResponse {
+ export interface PhoneNumber {
+ /**
+ * The date and time when the phone number was added to the list.
+ */
+ created_at: string;
+
+ /**
+ * An E.164 formatted phone number.
+ */
+ phone_number: string;
+ }
+}
+
+/**
+ * A list of Sender ID.
+ */
+export interface VerificationManagementListSenderIDsResponse {
+ sender_ids?: Array;
+}
+
+export namespace VerificationManagementListSenderIDsResponse {
+ export interface SenderID {
+ /**
+ * Value that will be presented as Sender ID
+ */
+ sender_id?: string;
+
+ /**
+ * It indicates the status of the Sender ID. Possible values are:
+ *
+ * - `approved` - The Sender ID is approved.
+ * - `pending` - The Sender ID is pending.
+ * - `rejected` - The Sender ID is rejected.
+ */
+ status?: 'approved' | 'pending' | 'rejected';
+ }
+}
+
+export interface VerificationManagementSetPhoneNumberResponse {
+ /**
+ * The E.164 formatted phone number that was added to the list.
+ */
+ phone_number: string;
+}
+
+export interface VerificationManagementSubmitSenderIDResponse {
+ /**
+ * The sender ID that was added.
+ */
+ sender_id: string;
+
+ /**
+ * It indicates the status of the sender ID. Possible values are:
+ *
+ * - `approved` - The sender ID is approved.
+ * - `pending` - The sender ID is pending.
+ * - `rejected` - The sender ID is rejected.
+ */
+ status: 'approved' | 'pending' | 'rejected';
+
+ /**
+ * The reason why the sender ID was rejected.
+ */
+ reason?: string;
+}
+
+export interface VerificationManagementDeletePhoneNumberParams {
+ /**
+ * An E.164 formatted phone number to remove from the list.
+ */
+ phone_number: string;
+}
+
+export interface VerificationManagementSetPhoneNumberParams {
+ /**
+ * An E.164 formatted phone number to add to the list.
+ */
+ phone_number: string;
+}
+
+export interface VerificationManagementSubmitSenderIDParams {
+ /**
+ * The sender ID to add.
+ */
+ sender_id: string;
+}
+
+VerificationManagement.Sandbox = Sandbox;
+
+export declare namespace VerificationManagement {
+ export {
+ type VerificationManagementDeletePhoneNumberResponse as VerificationManagementDeletePhoneNumberResponse,
+ type VerificationManagementListPhoneNumbersResponse as VerificationManagementListPhoneNumbersResponse,
+ type VerificationManagementListSenderIDsResponse as VerificationManagementListSenderIDsResponse,
+ type VerificationManagementSetPhoneNumberResponse as VerificationManagementSetPhoneNumberResponse,
+ type VerificationManagementSubmitSenderIDResponse as VerificationManagementSubmitSenderIDResponse,
+ type VerificationManagementDeletePhoneNumberParams as VerificationManagementDeletePhoneNumberParams,
+ type VerificationManagementSetPhoneNumberParams as VerificationManagementSetPhoneNumberParams,
+ type VerificationManagementSubmitSenderIDParams as VerificationManagementSubmitSenderIDParams,
+ };
+
+ export {
+ Sandbox as Sandbox,
+ type SandboxAddPhoneNumberResponse as SandboxAddPhoneNumberResponse,
+ type SandboxDeletePhoneNumberResponse as SandboxDeletePhoneNumberResponse,
+ type SandboxListPhoneNumbersResponse as SandboxListPhoneNumbersResponse,
+ type SandboxAddPhoneNumberParams as SandboxAddPhoneNumberParams,
+ };
+}
diff --git a/src/resources/verification.ts b/src/resources/verification.ts
index 5ab1656..d46fce2 100644
--- a/src/resources/verification.ts
+++ b/src/resources/verification.ts
@@ -1,559 +1,3 @@
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
-import { APIResource } from '../resource';
-import * as Core from '../core';
-
-/**
- * Verify phone numbers.
- */
-export class Verification extends APIResource {
- /**
- * Create a new verification for a specific phone number. If another non-expired
- * verification exists (the request is performed within the verification window),
- * this endpoint will perform a retry instead.
- *
- * @example
- * ```ts
- * const verification = await client.verification.create({
- * target: { type: 'phone_number', value: '+30123456789' },
- * });
- * ```
- */
- create(
- body: VerificationCreateParams,
- options?: Core.RequestOptions,
- ): Core.APIPromise {
- return this._client.post('/v2/verification', { body, ...options });
- }
-
- /**
- * Check the validity of a verification code.
- *
- * @example
- * ```ts
- * const response = await client.verification.check({
- * code: '12345',
- * target: { type: 'phone_number', value: '+30123456789' },
- * });
- * ```
- */
- check(
- body: VerificationCheckParams,
- options?: Core.RequestOptions,
- ): Core.APIPromise {
- return this._client.post('/v2/verification/check', { body, ...options });
- }
-}
-
-export interface VerificationCreateResponse {
- /**
- * The verification identifier.
- */
- id: string;
-
- /**
- * The method used for verifying this phone number.
- */
- method: 'email' | 'message' | 'silent' | 'voice';
-
- /**
- * The status of the verification.
- *
- * - `success` - A new verification window was created.
- * - `retry` - A new attempt was created for an existing verification window.
- * - `challenged` - The verification is suspicious and is restricted to non-SMS and
- * non-voice channels only. This mode must be enabled for your customer account
- * by Prelude support.
- * - `blocked` - The verification was blocked.
- * - `shadow_blocked` - The verification triggered a block rule but the decision
- * was not enforced; this is used to dry-run anti-fraud configuration. This mode
- * must be enabled for your customer account by Prelude support.
- */
- status: 'success' | 'retry' | 'challenged' | 'blocked' | 'shadow_blocked';
-
- /**
- * The ordered sequence of channels to be used for verification
- */
- channels?: Array<'rcs' | 'silent' | 'sms' | 'telegram' | 'viber' | 'voice' | 'whatsapp' | 'zalo'>;
-
- /**
- * The metadata for this verification.
- */
- metadata?: VerificationCreateResponse.Metadata;
-
- /**
- * The reason why the verification was blocked. Only present when status is
- * "blocked" or "shadow_blocked".
- *
- * - `expired_signature` - The signature of the SDK signals is expired. They should
- * be sent within the hour following their collection.
- * - `in_block_list` - The phone number is part of the configured block list.
- * - `invalid_phone_line` - The phone number is not a valid line number (e.g.
- * landline).
- * - `invalid_phone_number` - The phone number is not a valid phone number (e.g.
- * unallocated range).
- * - `invalid_signature` - The signature of the SDK signals is invalid.
- * - `repeated_attempts` - The phone number has made too many verification
- * attempts.
- * - `suspicious` - The verification attempt was deemed suspicious by the
- * anti-fraud system.
- */
- reason?:
- | 'expired_signature'
- | 'in_block_list'
- | 'invalid_phone_line'
- | 'invalid_phone_number'
- | 'invalid_signature'
- | 'repeated_attempts'
- | 'suspicious';
-
- request_id?: string;
-
- /**
- * The risk factors that contributed to the verification being blocked. Only
- * present when status is "blocked" or "shadow_blocked" and the anti-fraud system
- * detected specific risk signals.
- *
- * - `behavioral_pattern` - The phone number past behavior during verification
- * flows exhibits suspicious patterns.
- * - `device_attribute` - The device exhibits characteristics associated with
- * suspicious activity patterns.
- * - `fraud_database` - The phone number has been flagged as suspicious in one or
- * more of our fraud databases.
- * - `location_discrepancy` - The phone number prefix and IP address discrepancy
- * indicates potential fraud.
- * - `network_fingerprint` - The network connection exhibits characteristics
- * associated with suspicious activity patterns.
- * - `poor_conversion_history` - The phone number has a history of poorly
- * converting to a verified phone number.
- * - `prefix_concentration` - The phone number is part of a range known to be
- * associated with suspicious activity patterns.
- * - `suspected_request_tampering` - The SDK signature is invalid and the request
- * is considered to be tampered with.
- * - `suspicious_ip_address` - The IP address is deemed to be associated with
- * suspicious activity patterns.
- * - `temporary_phone_number` - The phone number is known to be a temporary or
- * disposable number.
- */
- risk_factors?: Array<
- | 'behavioral_pattern'
- | 'device_attribute'
- | 'fraud_database'
- | 'location_discrepancy'
- | 'network_fingerprint'
- | 'poor_conversion_history'
- | 'prefix_concentration'
- | 'suspected_request_tampering'
- | 'suspicious_ip_address'
- | 'temporary_phone_number'
- >;
-
- /**
- * The silent verification specific properties.
- */
- silent?: VerificationCreateResponse.Silent;
-}
-
-export namespace VerificationCreateResponse {
- /**
- * The metadata for this verification.
- */
- export interface Metadata {
- /**
- * A user-defined identifier to correlate this verification with. It is returned in
- * the response and any webhook events that refer to this verification.
- */
- correlation_id?: string;
- }
-
- /**
- * The silent verification specific properties.
- */
- export interface Silent {
- /**
- * The URL to start the silent verification towards.
- */
- request_url: string;
- }
-}
-
-export interface VerificationCheckResponse {
- /**
- * The status of the check. For `prelude:psd2` codes, `transaction_missing` is
- * returned when the `psd2` block is omitted, and `transaction_mismatch` when the
- * submitted variables differ from those provided at issuance.
- */
- status: 'success' | 'failure' | 'expired_or_not_found' | 'transaction_missing' | 'transaction_mismatch';
-
- /**
- * The verification identifier.
- */
- id?: string;
-
- /**
- * The metadata for this verification.
- */
- metadata?: VerificationCheckResponse.Metadata;
-
- request_id?: string;
-}
-
-export namespace VerificationCheckResponse {
- /**
- * The metadata for this verification.
- */
- export interface Metadata {
- /**
- * A user-defined identifier to correlate this verification with. It is returned in
- * the response and any webhook events that refer to this verification.
- */
- correlation_id?: string;
- }
-}
-
-export interface VerificationCreateParams {
- /**
- * The verification target. Either a phone number or an email address. To use the
- * email verification feature contact us to discuss your use case.
- */
- target: VerificationCreateParams.Target;
-
- /**
- * The identifier of the dispatch that came from the front-end SDK.
- */
- dispatch_id?: string;
-
- /**
- * The metadata for this verification. This object will be returned with every
- * response or webhook sent that refers to this verification.
- */
- metadata?: VerificationCreateParams.Metadata;
-
- /**
- * Verification options
- */
- options?: VerificationCreateParams.Options;
-
- /**
- * The signals used for anti-fraud. For more details, refer to
- * [Signals](/verify/v2/documentation/prevent-fraud#signals).
- */
- signals?: VerificationCreateParams.Signals;
-}
-
-export namespace VerificationCreateParams {
- /**
- * The verification target. Either a phone number or an email address. To use the
- * email verification feature contact us to discuss your use case.
- */
- export interface Target {
- /**
- * The type of the target. Either "phone_number" or "email_address".
- */
- type: 'phone_number' | 'email_address';
-
- /**
- * An E.164 formatted phone number or an email address.
- */
- value: string;
- }
-
- /**
- * The metadata for this verification. This object will be returned with every
- * response or webhook sent that refers to this verification.
- */
- export interface Metadata {
- /**
- * A user-defined identifier to correlate this verification with. It is returned in
- * the response and any webhook events that refer to this verification.
- */
- correlation_id?: string;
- }
-
- /**
- * Verification options
- */
- export interface Options {
- /**
- * This allows automatic OTP retrieval on mobile apps and web browsers. Supported
- * platforms are Android (SMS Retriever API) and Web (WebOTP API).
- */
- app_realm?: Options.AppRealm;
-
- /**
- * The URL where webhooks will be sent when verification events occur, including
- * verification creation, attempt creation, and delivery status changes. For more
- * details, refer to [Webhook](/verify/v2/documentation/webhook).
- */
- callback_url?: string;
-
- /**
- * The channels this verification may use, in the order they are tried. Channels
- * you omit are never used, including on retries. This option can only be set when
- * the verification is created. The list is recorded on the verification and
- * applies for its whole lifecycle, so `channels` sent while retrying an existing
- * verification is ignored — unlike `preferred_channel`, which is honored on every
- * retry. Every channel you list must be enabled on your account and active in the
- * destination country, otherwise the request fails with
- * `channel_not_enabled_in_region`. Prelude still picks the best provider within
- * each channel. Cannot be combined with `preferred_channel`. Voice is requested
- * through `method` instead. Disabled by default — contact support to enable it.
- */
- channels?: Array<'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram'>;
-
- /**
- * The size of the code generated. It should be between 4 and 8. Defaults to the
- * code size specified from the Dashboard.
- */
- code_size?: number;
-
- /**
- * The custom code to use for OTP verification. To use the custom code feature,
- * contact us to enable it for your account. For more details, refer to
- * [Custom Code](/verify/v2/documentation/custom-codes).
- */
- custom_code?: string;
-
- /**
- * When `true`, the verification is routed through challenge-safe channels
- * (non-SMS/Voice) regardless of country eligibility or any antispam outcome. The
- * resulting verification has `status: "challenged"`. Use this when you have your
- * own signal that the request is suspicious and want stricter routing — the
- * verification is **not** classified as fraud and does not contribute to
- * anti-fraud counters or risk factors. This feature is disabled by default —
- * contact Prelude support to enable it on your account.
- */
- force_challenge?: boolean;
-
- /**
- * A BCP-47 formatted locale string with the language the text message will be sent
- * to. If there's no locale set, the language will be determined by the country
- * code of the phone number. If the language specified doesn't exist, it defaults
- * to US English.
- */
- locale?: string;
-
- /**
- * Maximum number of delivery attempts Prelude may add on its own after the one you
- * requested. `0` means a single attempt: if it cannot be delivered, Prelude
- * neither tries another provider nor another channel, and does not retry
- * automatically. `1` allows one additional attempt, and so on — a value larger
- * than the number of routes available for the destination simply behaves like the
- * default. When omitted, Prelude retries as your account is configured, across as
- * many channels as the route offers.
- *
- * This option can only be set when the verification is created. The value is
- * recorded on the verification and applies for its whole lifecycle, so a
- * `max_auto_fallbacks` sent while retrying an existing verification is ignored —
- * the limit cannot be raised or lowered after the fact. A retry you ask for is not
- * an automatic attempt, so it gets a fresh allowance of the same limit. This
- * option is disabled by default — contact Prelude support to enable it on your
- * account.
- */
- max_auto_fallbacks?: number;
-
- /**
- * The method used for verifying this phone number. The 'voice' option provides an
- * accessible alternative for visually impaired users by delivering the
- * verification code through a phone call rather than a text message. It also
- * allows verification of landline numbers that cannot receive SMS messages. The
- * 'message' option explicitly requests message delivery (SMS, WhatsApp ...) and
- * skips silent verification, useful for scenarios requiring direct user
- * interaction.
- */
- method?: 'auto' | 'voice' | 'message';
-
- /**
- * The channel to prioritize when delivering the verification. Prelude prioritizes
- * this channel on the first attempt and continues to prefer it on retries while an
- * untried route on that channel remains; once those are exhausted, retries fall
- * back to the next best available route. If the channel is unavailable (for
- * example, when a verification is challenged), Prelude uses the best available
- * route instead. Cannot be combined with `channels`.
- */
- preferred_channel?: 'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram';
-
- /**
- * The Sender ID to use for this message. The Sender ID needs to be enabled by
- * Prelude.
- */
- sender_id?: string;
-
- /**
- * The identifier of a verification template. It applies use case-specific
- * settings, such as the message content or certain verification parameters.
- */
- template_id?: string;
-
- /**
- * The variables to be replaced in the template.
- */
- variables?: { [key: string]: string };
- }
-
- export namespace Options {
- /**
- * This allows automatic OTP retrieval on mobile apps and web browsers. Supported
- * platforms are Android (SMS Retriever API) and Web (WebOTP API).
- */
- export interface AppRealm {
- /**
- * The platform for automatic OTP retrieval. Use "android" for the SMS Retriever
- * API or "web" for the WebOTP API.
- */
- platform: 'android' | 'web';
-
- /**
- * The value depends on the platform:
- *
- * - For Android: The SMS Retriever API hash code (11 characters). See
- * [Google documentation](https://developers.google.com/identity/sms-retriever/verify#computing_your_apps_hash_string).
- * - For Web: The origin domain (e.g., "example.com" or "www.example.com"). See
- * [WebOTP API documentation](https://developer.mozilla.org/en-US/docs/Web/API/WebOTP_API).
- */
- value: string;
- }
- }
-
- /**
- * The signals used for anti-fraud. For more details, refer to
- * [Signals](/verify/v2/documentation/prevent-fraud#signals).
- */
- export interface Signals {
- /**
- * The version of your application.
- */
- app_version?: string;
-
- /**
- * A unique ID for the user's device. You should ensure that each user device has a
- * unique `device_id` value. Ideally, for Android, this corresponds to the
- * `ANDROID_ID` and for iOS, this corresponds to the `identifierForVendor`.
- */
- device_id?: string;
-
- /**
- * The model of the user's device.
- */
- device_model?: string;
-
- /**
- * The type of the user's device.
- */
- device_platform?: 'android' | 'ios' | 'ipados' | 'tvos' | 'web';
-
- /**
- * Whether the end-user already exists in your system, for example an existing
- * account signing in again rather than a first-time signup. Unlike
- * `is_trusted_user`, this signal does not bypass fraud checks; it is taken into
- * account as one additional anti-fraud signal. For more details, refer to
- * [Signals](/verify/v2/documentation/prevent-fraud#signals).
- */
- existing_user?: boolean;
-
- /**
- * The public IP v4 or v6 address of the end-user's device. You should collect this
- * from your backend. If your backend is behind a proxy, use the `X-Forwarded-For`,
- * `Forwarded`, `True-Client-IP`, `CF-Connecting-IP` or an equivalent header to get
- * the actual public IP of the end-user's device.
- */
- ip?: string;
-
- /**
- * This signal should indicate a higher level of trust, explicitly stating that the
- * user is genuine. Contact us to discuss your use case. For more details, refer to
- * [Signals](/verify/v2/documentation/prevent-fraud#signals).
- */
- is_trusted_user?: boolean;
-
- /**
- * The JA4 fingerprint observed for the end-user's connection. Prelude will infer
- * it automatically when you use our Frontend SDKs (which use Prelude's edge
- * network), but you can also forward the value if you terminate TLS yourself.
- */
- ja4_fingerprint?: string;
-
- /**
- * The version of the user's device operating system.
- */
- os_version?: string;
-
- /**
- * The user agent of the user's device. If the individual fields (os_version,
- * device_platform, device_model) are provided, we will prioritize those values
- * instead of parsing them from the user agent string.
- */
- user_agent?: string;
- }
-}
-
-export interface VerificationCheckParams {
- /**
- * The OTP code to validate.
- */
- code: string;
-
- /**
- * The verification target. Either a phone number or an email address. To use the
- * email verification feature contact us to discuss your use case.
- */
- target: VerificationCheckParams.Target;
-
- /**
- * Required when checking a code issued under the `prelude:psd2` template. The
- * submitted variables must match those provided at issuance; any mismatch
- * invalidates the code (PSD2 SCA RTS Article 5 dynamic linking). Ignored on
- * non-PSD2 verifications.
- */
- psd2?: VerificationCheckParams.Psd2;
-}
-
-export namespace VerificationCheckParams {
- /**
- * The verification target. Either a phone number or an email address. To use the
- * email verification feature contact us to discuss your use case.
- */
- export interface Target {
- /**
- * The type of the target. Either "phone_number" or "email_address".
- */
- type: 'phone_number' | 'email_address';
-
- /**
- * An E.164 formatted phone number or an email address.
- */
- value: string;
- }
-
- /**
- * Required when checking a code issued under the `prelude:psd2` template. The
- * submitted variables must match those provided at issuance; any mismatch
- * invalidates the code (PSD2 SCA RTS Article 5 dynamic linking). Ignored on
- * non-PSD2 verifications.
- */
- export interface Psd2 {
- /**
- * Decimal amount of the transaction.
- */
- amount: string;
-
- /**
- * ISO 4217 currency code.
- */
- currency: string;
-
- /**
- * Payee name displayed to the payer.
- */
- recipient: string;
- }
-}
-
-export declare namespace Verification {
- export {
- type VerificationCreateResponse as VerificationCreateResponse,
- type VerificationCheckResponse as VerificationCheckResponse,
- type VerificationCreateParams as VerificationCreateParams,
- type VerificationCheckParams as VerificationCheckParams,
- };
-}
+export * from './verification/index';
diff --git a/src/resources/verification/index.ts b/src/resources/verification/index.ts
new file mode 100644
index 0000000..46ed84d
--- /dev/null
+++ b/src/resources/verification/index.ts
@@ -0,0 +1,10 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export { Phone } from './phone/index';
+export {
+ Verification,
+ type VerificationCreateResponse,
+ type VerificationCheckResponse,
+ type VerificationCreateParams,
+ type VerificationCheckParams,
+} from './verification';
diff --git a/src/resources/verification/phone.ts b/src/resources/verification/phone.ts
new file mode 100644
index 0000000..a53cf49
--- /dev/null
+++ b/src/resources/verification/phone.ts
@@ -0,0 +1,3 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export * from './phone/index';
diff --git a/src/resources/verification/phone/history.ts b/src/resources/verification/phone/history.ts
new file mode 100644
index 0000000..7bab12d
--- /dev/null
+++ b/src/resources/verification/phone/history.ts
@@ -0,0 +1,681 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../../resource';
+import { isRequestOptions } from '../../../core';
+import * as Core from '../../../core';
+import * as HistoryAPI from './history';
+
+/**
+ * Verify phone numbers.
+ */
+export class History extends APIResource {
+ /**
+ * Retrieve everything Prelude recorded for one phone verification: its outcome and
+ * the device, network and anti-fraud context it was created in, the chronological
+ * timeline of every message attempt and code check, and the anti-fraud signals you
+ * forwarded.
+ *
+ * The identifier is the `id` returned by
+ * [Create or retry a verification](/verify/v2/api-reference/create-or-retry-a-verification)
+ * or the `verification_id` of the verification webhooks. Both `lifecycle` and
+ * `signals` are optional: a verification can resolve with its top-level fields
+ * alone.
+ *
+ * @example
+ * ```ts
+ * const history =
+ * await client.verification.phone.history.retrieve(
+ * 'vrf_01jc0t6fwwfgfsq1md24mhyztj',
+ * );
+ * ```
+ */
+ retrieve(id: string, options?: Core.RequestOptions): Core.APIPromise {
+ return this._client.get(`/v2/verification/phone/history/${id}`, options);
+ }
+
+ /**
+ * List your phone verifications, most recent first, one entry per verification
+ * with its outcome, channels, attempts and cost. Every filter is optional and they
+ * combine with AND.
+ *
+ * Use it to find every verification a phone number went through from your support
+ * tooling, then
+ * [Get a phone verification](/verify/v2/api-reference/history/get-a-phone-verification)
+ * for the full timeline of one of them. A cursor is bound to the filters that
+ * produced it: pass `next_cursor` back with the exact same query parameters.
+ *
+ * @example
+ * ```ts
+ * const histories =
+ * await client.verification.phone.history.list();
+ * ```
+ */
+ list(query?: HistoryListParams, options?: Core.RequestOptions): Core.APIPromise;
+ list(options?: Core.RequestOptions): Core.APIPromise;
+ list(
+ query: HistoryListParams | Core.RequestOptions = {},
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ if (isRequestOptions(query)) {
+ return this.list({}, query);
+ }
+ return this._client.get('/v2/verification/phone/history', { query, ...options });
+ }
+}
+
+/**
+ * The end user's mobile network.
+ */
+export interface PhoneVerificationCarrier {
+ mccmnc: string;
+
+ name?: string;
+}
+
+export interface PhoneVerificationMoney {
+ /**
+ * Exact decimal amount. It is never rounded to the currency's minor units, so a
+ * sub-cent cost reads as `0.0004` rather than as `0.00`.
+ */
+ amount: string;
+
+ /**
+ * ISO 4217 currency code.
+ */
+ currency: string;
+}
+
+export interface PhoneVerificationPsd2Transaction {
+ amount?: PhoneVerificationMoney;
+
+ /**
+ * Payee name displayed to the payer.
+ */
+ recipient?: string;
+}
+
+/**
+ * A verification and everything Prelude recorded about it.
+ */
+export interface HistoryRetrieveResponse {
+ /**
+ * The verification identifier.
+ */
+ id: string;
+
+ created_at: string;
+
+ expires_at: string;
+
+ /**
+ * The E.164 phone number the verification targeted.
+ */
+ phone_number: string;
+
+ /**
+ * The outcome of the verification.
+ *
+ * - `converted` - The end user submitted a valid code.
+ * - `not_converted` - The verification expired without a valid code.
+ * - `pending_check` - A code was delivered and Prelude is still waiting for a
+ * check.
+ * - `sent` - A code was sent and the verification window is still open.
+ * - `challenged` - The verification was restricted to non-SMS and non-voice
+ * channels.
+ * - `suspected_fraud` - The anti-fraud system blocked the verification.
+ * - `in_blocklist` - The phone number is on the configured block list.
+ * - `invalid_line` - The phone number is not a valid line type.
+ * - `invalid_number` - The phone number is not a valid number.
+ * - `rate_limited` - The verification was refused by a rate limit.
+ * - `expired_signals` - The SDK signals were collected too long before the
+ * request.
+ * - `shadowed` - The anti-fraud system flagged the verification without blocking
+ * it.
+ */
+ status:
+ | 'converted'
+ | 'not_converted'
+ | 'pending_check'
+ | 'sent'
+ | 'challenged'
+ | 'suspected_fraud'
+ | 'in_blocklist'
+ | 'invalid_line'
+ | 'invalid_number'
+ | 'rate_limited'
+ | 'expired_signals'
+ | 'shadowed';
+
+ /**
+ * Version of your application, when known.
+ */
+ app_version?: string;
+
+ /**
+ * Why the anti-fraud system blocked the verification. Empty unless it did.
+ *
+ * - `behavioral_pattern` - The phone number past behavior during verification
+ * flows exhibits suspicious patterns.
+ * - `device_attribute` - The end-user device reported attributes associated with
+ * fraud or emulation.
+ * - `fraud_database` - The phone number appears in a fraud database.
+ * - `location_discrepancy` - The phone number region and the observed location
+ * disagree.
+ * - `missing_signals` - The verification expected Prelude SDK signals and none
+ * arrived.
+ * - `network_fingerprint` - The network fingerprint matches known fraudulent
+ * traffic.
+ * - `poor_conversion_history` - The phone number rarely completes the
+ * verifications it starts.
+ * - `prefix_concentration` - The phone number is part of a range known to be
+ * associated with suspicious activity patterns.
+ * - `repeated_number` - The phone number was used far more often than normal
+ * traffic would explain.
+ * - `suspected_request_tampering` - The SDK signals were altered or expired
+ * between collection and use.
+ * - `suspicious_ip_address` - The originating IP address is associated with
+ * suspicious activity.
+ * - `temporary_phone_number` - The phone number is known to be a temporary or
+ * disposable number.
+ */
+ block_reasons?: Array<
+ | 'behavioral_pattern'
+ | 'device_attribute'
+ | 'fraud_database'
+ | 'location_discrepancy'
+ | 'missing_signals'
+ | 'network_fingerprint'
+ | 'poor_conversion_history'
+ | 'prefix_concentration'
+ | 'repeated_number'
+ | 'suspected_request_tampering'
+ | 'suspicious_ip_address'
+ | 'temporary_phone_number'
+ >;
+
+ /**
+ * The end user's mobile network.
+ */
+ carrier?: PhoneVerificationCarrier;
+
+ /**
+ * The correlation identifier you supplied when creating the verification.
+ */
+ correlation_id?: string;
+
+ /**
+ * Model of the end-user device, when known.
+ */
+ device_model?: string;
+
+ /**
+ * Platform of the end-user device, when known.
+ */
+ device_platform?: 'android' | 'ios' | 'ipados' | 'tvos' | 'web';
+
+ /**
+ * IP address the verification was created from.
+ */
+ ip_address?: string;
+
+ /**
+ * ISO 3166-1 alpha-2 region of the caller's IP address.
+ */
+ ip_address_region?: string;
+
+ /**
+ * Distance between the phone number region and the IP location.
+ */
+ ip_distance_meters?: number;
+
+ /**
+ * Chronological timeline of the verification: creation, message attempts with
+ * delivery events, code checks and signals reception. Omitted when Prelude holds
+ * no timeline for the verification.
+ */
+ lifecycle?: HistoryRetrieveResponse.Lifecycle;
+
+ /**
+ * Whether the phone number was allow-listed, block-listed, or sandboxed at
+ * verification time.
+ */
+ phone_number_condition?: 'allow_listed' | 'block_listed' | 'sandboxed';
+
+ /**
+ * Whether the phone number is currently allow-listed, block-listed, or sandboxed.
+ */
+ phone_number_current_condition?: 'allow_listed' | 'block_listed' | 'sandboxed';
+
+ /**
+ * ISO 3166-1 alpha-2 region of the phone number.
+ */
+ phone_number_region?: string;
+
+ /**
+ * The anti-fraud signals you forwarded when creating the verification.
+ */
+ signals?: HistoryRetrieveResponse.Signals;
+
+ /**
+ * Whether the SDK signals integrity check passed.
+ */
+ signals_hash_status?: 'valid' | 'invalid';
+
+ /**
+ * The template used for this verification.
+ */
+ template_id?: string;
+}
+
+export namespace HistoryRetrieveResponse {
+ /**
+ * Chronological timeline of the verification: creation, message attempts with
+ * delivery events, code checks and signals reception. Omitted when Prelude holds
+ * no timeline for the verification.
+ */
+ export interface Lifecycle {
+ events: Array;
+
+ total_cost?: HistoryAPI.PhoneVerificationMoney;
+
+ /**
+ * How many times the message was reported undeliverable by independent routes.
+ * Above zero usually means the phone number is incorrect or the device
+ * unreachable.
+ */
+ undeliverable_route_count?: number;
+ }
+
+ export namespace Lifecycle {
+ /**
+ * One timeline entry. `type` names the single payload field that is set.
+ */
+ export interface Event {
+ type: 'create' | 'attempt' | 'check' | 'signals';
+
+ /**
+ * One message sent for this verification.
+ */
+ attempt?: Event.Attempt;
+
+ /**
+ * One code submission for this verification.
+ */
+ check?: Event.Check;
+
+ create?: Event.Create;
+
+ signals?: Event.Signals;
+ }
+
+ export namespace Event {
+ /**
+ * One message sent for this verification.
+ */
+ export interface Attempt {
+ id: string;
+
+ created_at: string;
+
+ /**
+ * The end user's mobile network.
+ */
+ carrier?: HistoryAPI.PhoneVerificationCarrier;
+
+ channel?: 'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram' | 'voice' | 'silent';
+
+ /**
+ * Message body. While the verification can still be completed, the code inside it
+ * is masked rather than removed.
+ */
+ content?: string;
+
+ cost?: HistoryAPI.PhoneVerificationMoney;
+
+ delivery_events?: Array;
+
+ delivery_status?: 'unknown' | 'in_transit' | 'delivered' | 'undeliverable' | 'read';
+
+ /**
+ * Channel you asked for, when it differs from the one used.
+ */
+ preferred_channel?: 'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram' | 'voice' | 'silent';
+
+ status?: 'succeeded' | 'failed';
+
+ /**
+ * What caused the attempt.
+ */
+ trigger?: 'initial' | 'auto_retry' | 'user_retry';
+ }
+
+ export namespace Attempt {
+ export interface DeliveryEvent {
+ received_at: string;
+
+ /**
+ * The state this event reported. It is finer-grained than the attempt's
+ * `delivery_status` and includes the states a silent verification goes through.
+ */
+ status:
+ | 'unknown'
+ | 'submitted'
+ | 'in_transit'
+ | 'delivered'
+ | 'undeliverable'
+ | 'expired'
+ | 'read'
+ | 'silent_started'
+ | 'silent_verified'
+ | 'silent_mismatch';
+ }
+ }
+
+ /**
+ * One code submission for this verification.
+ */
+ export interface Check {
+ created_at: string;
+
+ is_valid: boolean;
+
+ channel?: 'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram' | 'voice' | 'silent';
+
+ /**
+ * Present on checks against a `prelude:psd2` code.
+ */
+ psd2_info?: Check.Psd2Info;
+
+ /**
+ * Why an invalid check failed, when known.
+ */
+ status_detail?:
+ | 'expired_attempt'
+ | 'expired_auth'
+ | 'rate_limited'
+ | 'transaction_missing'
+ | 'transaction_mismatch';
+
+ /**
+ * The submitted code. Absent while the verification can still be completed, so
+ * that a check in flight cannot be read back through this endpoint, and absent on
+ * silent verification checks, which carry no code.
+ */
+ value?: string;
+ }
+
+ export namespace Check {
+ /**
+ * Present on checks against a `prelude:psd2` code.
+ */
+ export interface Psd2Info {
+ /**
+ * The transaction submitted when the code was issued.
+ */
+ expected_transaction?: HistoryAPI.PhoneVerificationPsd2Transaction;
+
+ /**
+ * The transaction submitted with this check. Differs from `expected_transaction`
+ * when `status_detail` is `transaction_mismatch`.
+ */
+ received_transaction?: HistoryAPI.PhoneVerificationPsd2Transaction;
+ }
+ }
+
+ export interface Create {
+ created_at: string;
+
+ cost?: HistoryAPI.PhoneVerificationMoney;
+ }
+
+ export interface Signals {
+ received_at: string;
+
+ expired_at?: string;
+
+ status?: 'valid' | 'invalid';
+ }
+ }
+ }
+
+ /**
+ * The anti-fraud signals you forwarded when creating the verification.
+ */
+ export interface Signals {
+ /**
+ * Whether you flagged this end user as trusted when creating the verification.
+ * Declared by you, not computed by Prelude.
+ */
+ is_trusted_user: boolean;
+
+ /**
+ * End-user device identifier you forwarded.
+ */
+ device_id?: string;
+
+ /**
+ * TLS fingerprint you forwarded.
+ */
+ ja4_fingerprint?: string;
+
+ os_version?: string;
+
+ user_agent?: string;
+ }
+}
+
+export interface HistoryListResponse {
+ /**
+ * The page of verifications, most recent first.
+ */
+ verifications: Array;
+
+ /**
+ * Pagination cursor for the next page of results. Omitted if there are no more
+ * pages.
+ */
+ next_cursor?: string;
+}
+
+export namespace HistoryListResponse {
+ /**
+ * One entry of the verification history.
+ * [Get a phone verification](/verify/v2/api-reference/history/get-a-phone-verification)
+ * returns the full record.
+ */
+ export interface Verification {
+ /**
+ * The verification identifier.
+ */
+ id: string;
+
+ /**
+ * The channels the verification could use, and which one the end user converted
+ * through. Empty when the verification used only channels this API does not list.
+ */
+ channels: Array;
+
+ created_at: string;
+
+ /**
+ * Whether at least one message was reported delivered.
+ */
+ delivered: boolean;
+
+ /**
+ * The E.164 phone number the verification targeted.
+ */
+ phone_number: string;
+
+ /**
+ * The outcome of the verification.
+ *
+ * - `converted` - The end user submitted a valid code.
+ * - `not_converted` - The verification expired without a valid code.
+ * - `pending_check` - A code was delivered and Prelude is still waiting for a
+ * check.
+ * - `sent` - A code was sent and the verification window is still open.
+ * - `challenged` - The verification was restricted to non-SMS and non-voice
+ * channels.
+ * - `suspected_fraud` - The anti-fraud system blocked the verification.
+ * - `in_blocklist` - The phone number is on the configured block list.
+ * - `invalid_line` - The phone number is not a valid line type.
+ * - `invalid_number` - The phone number is not a valid number.
+ * - `rate_limited` - The verification was refused by a rate limit.
+ * - `expired_signals` - The SDK signals were collected too long before the
+ * request.
+ * - `shadowed` - The anti-fraud system flagged the verification without blocking
+ * it.
+ */
+ status:
+ | 'converted'
+ | 'not_converted'
+ | 'pending_check'
+ | 'sent'
+ | 'challenged'
+ | 'suspected_fraud'
+ | 'in_blocklist'
+ | 'invalid_line'
+ | 'invalid_number'
+ | 'rate_limited'
+ | 'expired_signals'
+ | 'shadowed';
+
+ /**
+ * Number of messages sent for the verification, `0` when none was. Absent for
+ * sandboxed phone numbers.
+ */
+ attempts?: number;
+
+ /**
+ * When the end user submitted a valid code. Absent unless the verification
+ * converted.
+ */
+ converted_at?: string;
+
+ /**
+ * Total cost of the verification. Absent when nothing was billed.
+ */
+ cost?: HistoryAPI.PhoneVerificationMoney;
+
+ /**
+ * Platform of the end-user device, when known.
+ */
+ device_platform?: 'android' | 'ios' | 'ipados' | 'tvos' | 'web';
+
+ /**
+ * Whether the phone number was allow-listed, block-listed, or sandboxed at
+ * verification time.
+ */
+ phone_number_condition?: 'allow_listed' | 'block_listed' | 'sandboxed';
+
+ /**
+ * Whether the SDK signals integrity check passed.
+ */
+ signals_hash_status?: 'valid' | 'invalid';
+ }
+
+ export namespace Verification {
+ export interface Channel {
+ channel: 'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram' | 'voice' | 'silent';
+
+ /**
+ * Whether the end user submitted a valid code received through this channel.
+ */
+ converted: boolean;
+ }
+ }
+}
+
+export interface HistoryListParams {
+ /**
+ * Only verifications that could use one of these channels. Repeat the parameter
+ * for several values.
+ */
+ channels?: Array<'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram' | 'voice' | 'silent'>;
+
+ /**
+ * Pagination cursor from the previous response.
+ */
+ cursor?: string;
+
+ /**
+ * Only verifications created from this device platform.
+ */
+ device_platform?: 'android' | 'ios' | 'ipados' | 'tvos' | 'web';
+
+ /**
+ * Only verifications created at or after this RFC 3339 timestamp. Goes with `to`,
+ * at most 6 months apart. Without them the whole history is searched.
+ */
+ from?: string;
+
+ /**
+ * Maximum number of verifications to return per page.
+ */
+ limit?: number;
+
+ /**
+ * Only verifications that sent at most this many messages. `0` keeps the
+ * verifications that never sent one.
+ */
+ max_attempts?: number;
+
+ /**
+ * Only verifications that sent at least this many messages.
+ */
+ min_attempts?: number;
+
+ /**
+ * Only verifications targeting this E.164 phone number. The leading `+` may be
+ * omitted.
+ */
+ phone_number?: string;
+
+ /**
+ * Only verifications of phone numbers from this region, as an ISO 3166-1 alpha-2
+ * code.
+ */
+ region?: string;
+
+ /**
+ * Only verifications in this status. `pending_check` cannot be filtered on.
+ */
+ status?:
+ | 'converted'
+ | 'not_converted'
+ | 'pending_check'
+ | 'sent'
+ | 'challenged'
+ | 'suspected_fraud'
+ | 'in_blocklist'
+ | 'invalid_line'
+ | 'invalid_number'
+ | 'rate_limited'
+ | 'expired_signals'
+ | 'shadowed';
+
+ /**
+ * Only verifications sent with this template, as returned in `template_id` by
+ * [Get a phone verification](/verify/v2/api-reference/history/get-a-phone-verification).
+ * Built-in templates (`prelude:*`) cannot be filtered on.
+ */
+ template_id?: string;
+
+ /**
+ * Only verifications created at or before this RFC 3339 timestamp. Goes with
+ * `from`.
+ */
+ to?: string;
+}
+
+export declare namespace History {
+ export {
+ type PhoneVerificationCarrier as PhoneVerificationCarrier,
+ type PhoneVerificationMoney as PhoneVerificationMoney,
+ type PhoneVerificationPsd2Transaction as PhoneVerificationPsd2Transaction,
+ type HistoryRetrieveResponse as HistoryRetrieveResponse,
+ type HistoryListResponse as HistoryListResponse,
+ type HistoryListParams as HistoryListParams,
+ };
+}
diff --git a/src/resources/verification/phone/index.ts b/src/resources/verification/phone/index.ts
new file mode 100644
index 0000000..65bc643
--- /dev/null
+++ b/src/resources/verification/phone/index.ts
@@ -0,0 +1,12 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+export {
+ History,
+ type PhoneVerificationCarrier,
+ type PhoneVerificationMoney,
+ type PhoneVerificationPsd2Transaction,
+ type HistoryRetrieveResponse,
+ type HistoryListResponse,
+ type HistoryListParams,
+} from './history';
+export { Phone } from './phone';
diff --git a/src/resources/verification/phone/phone.ts b/src/resources/verification/phone/phone.ts
new file mode 100644
index 0000000..c989f8c
--- /dev/null
+++ b/src/resources/verification/phone/phone.ts
@@ -0,0 +1,31 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../../resource';
+import * as HistoryAPI from './history';
+import {
+ History,
+ HistoryListParams,
+ HistoryListResponse,
+ HistoryRetrieveResponse,
+ PhoneVerificationCarrier,
+ PhoneVerificationMoney,
+ PhoneVerificationPsd2Transaction,
+} from './history';
+
+export class Phone extends APIResource {
+ history: HistoryAPI.History = new HistoryAPI.History(this._client);
+}
+
+Phone.History = History;
+
+export declare namespace Phone {
+ export {
+ History as History,
+ type PhoneVerificationCarrier as PhoneVerificationCarrier,
+ type PhoneVerificationMoney as PhoneVerificationMoney,
+ type PhoneVerificationPsd2Transaction as PhoneVerificationPsd2Transaction,
+ type HistoryRetrieveResponse as HistoryRetrieveResponse,
+ type HistoryListResponse as HistoryListResponse,
+ type HistoryListParams as HistoryListParams,
+ };
+}
diff --git a/src/resources/verification/verification.ts b/src/resources/verification/verification.ts
new file mode 100644
index 0000000..d61a62e
--- /dev/null
+++ b/src/resources/verification/verification.ts
@@ -0,0 +1,465 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import { APIResource } from '../../resource';
+import * as Core from '../../core';
+import * as Shared from '../shared';
+import * as PhoneAPI from './phone/phone';
+import { Phone } from './phone/phone';
+
+/**
+ * Verify phone numbers.
+ */
+export class Verification extends APIResource {
+ phone: PhoneAPI.Phone = new PhoneAPI.Phone(this._client);
+
+ /**
+ * Create a new verification for a specific phone number. If another non-expired
+ * verification exists (the request is performed within the verification window),
+ * this endpoint will perform a retry instead.
+ *
+ * @example
+ * ```ts
+ * const verification = await client.verification.create({
+ * target: { type: 'phone_number', value: '+30123456789' },
+ * });
+ * ```
+ */
+ create(
+ body: VerificationCreateParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.post('/v2/verification', { body, ...options });
+ }
+
+ /**
+ * Check the validity of a verification code.
+ *
+ * @example
+ * ```ts
+ * const response = await client.verification.check({
+ * code: '12345',
+ * target: { type: 'phone_number', value: '+30123456789' },
+ * });
+ * ```
+ */
+ check(
+ body: VerificationCheckParams,
+ options?: Core.RequestOptions,
+ ): Core.APIPromise {
+ return this._client.post('/v2/verification/check', { body, ...options });
+ }
+}
+
+export interface VerificationCreateResponse {
+ /**
+ * The verification identifier.
+ */
+ id: string;
+
+ /**
+ * The method used for verifying this phone number.
+ */
+ method: 'email' | 'message' | 'silent' | 'voice';
+
+ /**
+ * The status of the verification.
+ *
+ * - `success` - A new verification window was created.
+ * - `retry` - A new attempt was created for an existing verification window.
+ * - `challenged` - The verification is suspicious and is restricted to non-SMS and
+ * non-voice channels only. This mode must be enabled for your customer account
+ * by Prelude support.
+ * - `blocked` - The verification was blocked.
+ * - `shadow_blocked` - The verification triggered a block rule but the decision
+ * was not enforced; this is used to dry-run anti-fraud configuration. This mode
+ * must be enabled for your customer account by Prelude support.
+ */
+ status: 'success' | 'retry' | 'challenged' | 'blocked' | 'shadow_blocked';
+
+ /**
+ * The ordered sequence of channels to be used for verification
+ */
+ channels?: Array<'rcs' | 'silent' | 'sms' | 'telegram' | 'viber' | 'voice' | 'whatsapp' | 'zalo'>;
+
+ /**
+ * The metadata for this verification.
+ */
+ metadata?: VerificationCreateResponse.Metadata;
+
+ /**
+ * The reason why the verification was blocked. Only present when status is
+ * "blocked" or "shadow_blocked".
+ *
+ * - `expired_signature` - The signature of the SDK signals is expired. They should
+ * be sent within the hour following their collection.
+ * - `in_block_list` - The phone number is part of the configured block list.
+ * - `invalid_phone_line` - The phone number is not a valid line number (e.g.
+ * landline).
+ * - `invalid_phone_number` - The phone number is not a valid phone number (e.g.
+ * unallocated range).
+ * - `invalid_signature` - The signature of the SDK signals is invalid.
+ * - `repeated_attempts` - The phone number has made too many verification
+ * attempts.
+ * - `suspicious` - The verification attempt was deemed suspicious by the
+ * anti-fraud system.
+ */
+ reason?:
+ | 'expired_signature'
+ | 'in_block_list'
+ | 'invalid_phone_line'
+ | 'invalid_phone_number'
+ | 'invalid_signature'
+ | 'repeated_attempts'
+ | 'suspicious';
+
+ request_id?: string;
+
+ /**
+ * The risk factors that contributed to the verification being blocked. Only
+ * present when status is "blocked" or "shadow_blocked" and the anti-fraud system
+ * detected specific risk signals.
+ *
+ * - `behavioral_pattern` - The phone number past behavior during verification
+ * flows exhibits suspicious patterns.
+ * - `device_attribute` - The device exhibits characteristics associated with
+ * suspicious activity patterns.
+ * - `fraud_database` - The phone number has been flagged as suspicious in one or
+ * more of our fraud databases.
+ * - `location_discrepancy` - The phone number prefix and IP address discrepancy
+ * indicates potential fraud.
+ * - `network_fingerprint` - The network connection exhibits characteristics
+ * associated with suspicious activity patterns.
+ * - `poor_conversion_history` - The phone number has a history of poorly
+ * converting to a verified phone number.
+ * - `prefix_concentration` - The phone number is part of a range known to be
+ * associated with suspicious activity patterns.
+ * - `suspected_request_tampering` - The SDK signature is invalid and the request
+ * is considered to be tampered with.
+ * - `suspicious_ip_address` - The IP address is deemed to be associated with
+ * suspicious activity patterns.
+ * - `temporary_phone_number` - The phone number is known to be a temporary or
+ * disposable number.
+ */
+ risk_factors?: Array<
+ | 'behavioral_pattern'
+ | 'device_attribute'
+ | 'fraud_database'
+ | 'location_discrepancy'
+ | 'network_fingerprint'
+ | 'poor_conversion_history'
+ | 'prefix_concentration'
+ | 'suspected_request_tampering'
+ | 'suspicious_ip_address'
+ | 'temporary_phone_number'
+ >;
+
+ /**
+ * The silent verification specific properties.
+ */
+ silent?: VerificationCreateResponse.Silent;
+}
+
+export namespace VerificationCreateResponse {
+ /**
+ * The metadata for this verification.
+ */
+ export interface Metadata {
+ /**
+ * A user-defined identifier to correlate this verification with. It is returned in
+ * the response and any webhook events that refer to this verification.
+ */
+ correlation_id?: string;
+ }
+
+ /**
+ * The silent verification specific properties.
+ */
+ export interface Silent {
+ /**
+ * The URL to start the silent verification towards.
+ */
+ request_url: string;
+ }
+}
+
+export interface VerificationCheckResponse {
+ /**
+ * The status of the check. For `prelude:psd2` codes, `transaction_missing` is
+ * returned when the `psd2` block is omitted, and `transaction_mismatch` when the
+ * submitted variables differ from those provided at issuance.
+ */
+ status: 'success' | 'failure' | 'expired_or_not_found' | 'transaction_missing' | 'transaction_mismatch';
+
+ /**
+ * The verification identifier.
+ */
+ id?: string;
+
+ /**
+ * The metadata for this verification.
+ */
+ metadata?: VerificationCheckResponse.Metadata;
+
+ request_id?: string;
+}
+
+export namespace VerificationCheckResponse {
+ /**
+ * The metadata for this verification.
+ */
+ export interface Metadata {
+ /**
+ * A user-defined identifier to correlate this verification with. It is returned in
+ * the response and any webhook events that refer to this verification.
+ */
+ correlation_id?: string;
+ }
+}
+
+export interface VerificationCreateParams {
+ /**
+ * The verification target. Either a phone number or an email address. To use the
+ * email verification feature contact us to discuss your use case.
+ */
+ target: Shared.Target;
+
+ /**
+ * The identifier of the dispatch that came from the front-end SDK.
+ */
+ dispatch_id?: string;
+
+ /**
+ * The metadata for this verification. This object will be returned with every
+ * response or webhook sent that refers to this verification.
+ */
+ metadata?: VerificationCreateParams.Metadata;
+
+ /**
+ * Verification options
+ */
+ options?: VerificationCreateParams.Options;
+
+ /**
+ * The signals used for anti-fraud. For more details, refer to
+ * [Signals](/verify/v2/documentation/prevent-fraud#signals).
+ */
+ signals?: Shared.Signals;
+}
+
+export namespace VerificationCreateParams {
+ /**
+ * The metadata for this verification. This object will be returned with every
+ * response or webhook sent that refers to this verification.
+ */
+ export interface Metadata {
+ /**
+ * A user-defined identifier to correlate this verification with. It is returned in
+ * the response and any webhook events that refer to this verification.
+ */
+ correlation_id?: string;
+ }
+
+ /**
+ * Verification options
+ */
+ export interface Options {
+ /**
+ * This allows automatic OTP retrieval on mobile apps and web browsers. Supported
+ * platforms are Android (SMS Retriever API) and Web (WebOTP API).
+ */
+ app_realm?: Options.AppRealm;
+
+ /**
+ * The URL where webhooks will be sent when verification events occur, including
+ * verification creation, attempt creation, and delivery status changes. For more
+ * details, refer to [Webhook](/verify/v2/documentation/webhook).
+ */
+ callback_url?: string;
+
+ /**
+ * The channels this verification may use, in the order they are tried. Channels
+ * you omit are never used, including on retries. This option can only be set when
+ * the verification is created. The list is recorded on the verification and
+ * applies for its whole lifecycle, so `channels` sent while retrying an existing
+ * verification is ignored — unlike `preferred_channel`, which is honored on every
+ * retry. Every channel you list must be enabled on your account and active in the
+ * destination country, otherwise the request fails with
+ * `channel_not_enabled_in_region`. Prelude still picks the best provider within
+ * each channel. Cannot be combined with `preferred_channel`. Voice is requested
+ * through `method` instead. Disabled by default — contact support to enable it.
+ */
+ channels?: Array<'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram'>;
+
+ /**
+ * The size of the code generated. It should be between 4 and 8. Defaults to the
+ * code size specified from the Dashboard.
+ */
+ code_size?: number;
+
+ /**
+ * The custom code to use for OTP verification. To use the custom code feature,
+ * contact us to enable it for your account. For more details, refer to
+ * [Custom Code](/verify/v2/documentation/custom-codes).
+ */
+ custom_code?: string;
+
+ /**
+ * When `true`, the verification is routed through challenge-safe channels
+ * (non-SMS/Voice) regardless of country eligibility or any antispam outcome. The
+ * resulting verification has `status: "challenged"`. Use this when you have your
+ * own signal that the request is suspicious and want stricter routing — the
+ * verification is **not** classified as fraud and does not contribute to
+ * anti-fraud counters or risk factors. This feature is disabled by default —
+ * contact Prelude support to enable it on your account.
+ */
+ force_challenge?: boolean;
+
+ /**
+ * A BCP-47 formatted locale string with the language the text message will be sent
+ * to. If there's no locale set, the language will be determined by the country
+ * code of the phone number. If the language specified doesn't exist, it defaults
+ * to US English.
+ */
+ locale?: string;
+
+ /**
+ * Maximum number of delivery attempts Prelude may add on its own after the one you
+ * requested. `0` means a single attempt: if it cannot be delivered, Prelude
+ * neither tries another provider nor another channel, and does not retry
+ * automatically. `1` allows one additional attempt, and so on — a value larger
+ * than the number of routes available for the destination simply behaves like the
+ * default. When omitted, Prelude retries as your account is configured, across as
+ * many channels as the route offers.
+ *
+ * This option can only be set when the verification is created. The value is
+ * recorded on the verification and applies for its whole lifecycle, so a
+ * `max_auto_fallbacks` sent while retrying an existing verification is ignored —
+ * the limit cannot be raised or lowered after the fact. A retry you ask for is not
+ * an automatic attempt, so it gets a fresh allowance of the same limit. This
+ * option is disabled by default — contact Prelude support to enable it on your
+ * account.
+ */
+ max_auto_fallbacks?: number;
+
+ /**
+ * The method used for verifying this phone number. The 'voice' option provides an
+ * accessible alternative for visually impaired users by delivering the
+ * verification code through a phone call rather than a text message. It also
+ * allows verification of landline numbers that cannot receive SMS messages. The
+ * 'message' option explicitly requests message delivery (SMS, WhatsApp ...) and
+ * skips silent verification, useful for scenarios requiring direct user
+ * interaction.
+ */
+ method?: 'auto' | 'voice' | 'message';
+
+ /**
+ * The channel to prioritize when delivering the verification. Prelude prioritizes
+ * this channel on the first attempt and continues to prefer it on retries while an
+ * untried route on that channel remains; once those are exhausted, retries fall
+ * back to the next best available route. If the channel is unavailable (for
+ * example, when a verification is challenged), Prelude uses the best available
+ * route instead. Cannot be combined with `channels`.
+ */
+ preferred_channel?: 'sms' | 'rcs' | 'whatsapp' | 'viber' | 'zalo' | 'telegram';
+
+ /**
+ * The Sender ID to use for this message. The Sender ID needs to be enabled by
+ * Prelude.
+ */
+ sender_id?: string;
+
+ /**
+ * The identifier of a verification template. It applies use case-specific
+ * settings, such as the message content or certain verification parameters.
+ */
+ template_id?: string;
+
+ /**
+ * The variables to be replaced in the template.
+ */
+ variables?: { [key: string]: string };
+ }
+
+ export namespace Options {
+ /**
+ * This allows automatic OTP retrieval on mobile apps and web browsers. Supported
+ * platforms are Android (SMS Retriever API) and Web (WebOTP API).
+ */
+ export interface AppRealm {
+ /**
+ * The platform for automatic OTP retrieval. Use "android" for the SMS Retriever
+ * API or "web" for the WebOTP API.
+ */
+ platform: 'android' | 'web';
+
+ /**
+ * The value depends on the platform:
+ *
+ * - For Android: The SMS Retriever API hash code (11 characters). See
+ * [Google documentation](https://developers.google.com/identity/sms-retriever/verify#computing_your_apps_hash_string).
+ * - For Web: The origin domain (e.g., "example.com" or "www.example.com"). See
+ * [WebOTP API documentation](https://developer.mozilla.org/en-US/docs/Web/API/WebOTP_API).
+ */
+ value: string;
+ }
+ }
+}
+
+export interface VerificationCheckParams {
+ /**
+ * The OTP code to validate.
+ */
+ code: string;
+
+ /**
+ * The verification target. Either a phone number or an email address. To use the
+ * email verification feature contact us to discuss your use case.
+ */
+ target: Shared.Target;
+
+ /**
+ * Required when checking a code issued under the `prelude:psd2` template. The
+ * submitted variables must match those provided at issuance; any mismatch
+ * invalidates the code (PSD2 SCA RTS Article 5 dynamic linking). Ignored on
+ * non-PSD2 verifications.
+ */
+ psd2?: VerificationCheckParams.Psd2;
+}
+
+export namespace VerificationCheckParams {
+ /**
+ * Required when checking a code issued under the `prelude:psd2` template. The
+ * submitted variables must match those provided at issuance; any mismatch
+ * invalidates the code (PSD2 SCA RTS Article 5 dynamic linking). Ignored on
+ * non-PSD2 verifications.
+ */
+ export interface Psd2 {
+ /**
+ * Decimal amount of the transaction.
+ */
+ amount: string;
+
+ /**
+ * ISO 4217 currency code.
+ */
+ currency: string;
+
+ /**
+ * Payee name displayed to the payer.
+ */
+ recipient: string;
+ }
+}
+
+Verification.Phone = Phone;
+
+export declare namespace Verification {
+ export {
+ type VerificationCreateResponse as VerificationCreateResponse,
+ type VerificationCheckResponse as VerificationCheckResponse,
+ type VerificationCreateParams as VerificationCreateParams,
+ type VerificationCheckParams as VerificationCheckParams,
+ };
+
+ export { Phone as Phone };
+}
diff --git a/src/resources/watch.ts b/src/resources/watch.ts
index e2c7f19..9da25ba 100644
--- a/src/resources/watch.ts
+++ b/src/resources/watch.ts
@@ -2,11 +2,37 @@
import { APIResource } from '../resource';
import * as Core from '../core';
+import * as Shared from './shared';
/**
* Evaluate email addresses and phone numbers for trustworthiness.
*/
export class Watch extends APIResource {
+ /**
+ * **Beta.** The request and response shapes may still change, and flows and
+ * recipes are configured by Prelude on your behalf for now. Talk to us before you
+ * build against it.
+ *
+ * Score a target against the rules configured for one moment in your product —
+ * signup, checkout, password reset. The flow selects which recipes run; each
+ * recipe scores its rules against a threshold and returns its own verdict, and the
+ * evaluation answers with the most severe verdict and action across them. Where
+ * Predict returns a single model-derived outcome, Eval returns the full breakdown,
+ * so you can see which rules fired and which could not run. Scoring-only — it does
+ * not update counters by itself.
+ *
+ * @example
+ * ```ts
+ * const response = await client.watch.evaluate({
+ * flow_id: 'flo_01jc0t6fwwfgfsq1md24mhyztj',
+ * target: { type: 'phone_number', value: '+30123456789' },
+ * });
+ * ```
+ */
+ evaluate(body: WatchEvaluateParams, options?: Core.RequestOptions): Core.APIPromise {
+ return this._client.post('/v2/watch/eval', { body, ...options });
+ }
+
/**
* At signup, score the user's phone number or email address (target) as legitimate
* or suspicious. Scoring-only — does not update counters by itself. When using
@@ -88,6 +114,135 @@ export class Watch extends APIResource {
}
}
+export interface WatchEvaluateResponse {
+ /**
+ * The evaluation identifier.
+ */
+ id: string;
+
+ /**
+ * What the evaluation suggests you do, being the most severe action across the
+ * recipes that ran. Advisory: enforcement is yours.
+ *
+ * - `ALLOW` - Let the request through.
+ * - `BLOCK` - Refuse the request.
+ * - `CHALLENGE` - Let the request through behind an additional check.
+ */
+ action: 'ALLOW' | 'BLOCK' | 'CHALLENGE';
+
+ /**
+ * One result per recipe that ran. A recipe the flow names but that is not in
+ * service is absent rather than reported as having passed.
+ */
+ recipes: Array;
+
+ /**
+ * The evaluation-level verdict, being the most severe verdict across the recipes
+ * that ran.
+ *
+ * - `PASS` - No recipe flagged.
+ * - `FLAG` - At least one recipe flagged.
+ */
+ verdict: 'PASS' | 'FLAG';
+}
+
+export namespace WatchEvaluateResponse {
+ export interface Recipe {
+ /**
+ * At least one rule could not be evaluated, so the score rests on less than the
+ * whole recipe. The score is still returned — a partial verdict is more useful
+ * than none — but it is labeled rather than passed off as whole.
+ */
+ partial_evidence: boolean;
+
+ /**
+ * The recipe that produced this result.
+ */
+ recipe_id: string;
+
+ /**
+ * One result per rule in the recipe, in membership order. Every rule runs — a
+ * score is only meaningful when complete, so there is no short-circuit on the
+ * first trigger.
+ */
+ rules: Array;
+
+ /**
+ * The sum of the weights of the rules that triggered, clamped to the range -100
+ * to 100. Two scores at a bound are not comparable.
+ */
+ score: number;
+
+ /**
+ * The score at or above which this recipe flags.
+ */
+ threshold: number;
+
+ /**
+ * This recipe's own verdict. Normally the score against the threshold, unless a
+ * preempting rule fired — see `determined_by`.
+ */
+ verdict: 'PASS' | 'FLAG';
+
+ /**
+ * The preempting rule that set `verdict`, present only when a rule rather than the
+ * score decided it. Without it a recipe can report a score under its threshold and
+ * still flag, with nothing in the payload accounting for the difference.
+ */
+ determined_by?: string;
+ }
+
+ export namespace Recipe {
+ export interface Rule {
+ /**
+ * What the rule concluded.
+ *
+ * - `TRIGGERED` - The condition held; `weight` was added to the score.
+ * - `NOT_TRIGGERED` - The condition did not hold.
+ * - `NOT_EVALUATED` - The rule could not run, because something it reads never
+ * arrived. This is not a quieter `NOT_TRIGGERED`: it contributed nothing either
+ * way, and it is why `partial_evidence` is set on the recipe.
+ */
+ outcome: 'TRIGGERED' | 'NOT_TRIGGERED' | 'NOT_EVALUATED';
+
+ /**
+ * The rule that produced this result. Present whatever the rule's visibility, so a
+ * rule you cannot see the condition of is still one you can reweight, switch off,
+ * or ask us about.
+ */
+ rule_id: string;
+
+ /**
+ * What this rule contributes to the recipe's score when it triggers.
+ */
+ weight: number;
+
+ /**
+ * Why the rule could not run, set only when `outcome` is `NOT_EVALUATED`.
+ *
+ * A rule you authored names the signal or attribute it waited on, since you wrote
+ * the expression that reads it. A Prelude-managed rule reports `missing_data` and
+ * nothing more: the signal it waited on is part of a condition that is not
+ * disclosed.
+ */
+ blocked_by?: string;
+
+ /**
+ * The rule's name, present for a rule you authored and omitted for a
+ * Prelude-managed one. A managed rule's name describes what it looks for, which is
+ * as much of the condition as the expression is.
+ */
+ name?: string;
+
+ /**
+ * The rule could not run for a reason on our side rather than anything about your
+ * request. `outcome` is `NOT_EVALUATED` and the failure is ours to fix.
+ */
+ unavailable?: boolean;
+ }
+ }
+}
+
export interface WatchPredictResponse {
/**
* The prediction identifier.
@@ -175,125 +330,77 @@ export interface WatchSendFeedbacksResponse {
status: 'success';
}
-export interface WatchPredictParams {
+export interface WatchEvaluateParams {
/**
- * The signup identifier to score — a phone number or email address.
+ * The flow to evaluate. A flow names the moment you are guarding and selects the
+ * recipes that run.
*/
- target: WatchPredictParams.Target;
+ flow_id: string;
/**
- * The identifier of the dispatch that came from the front-end SDK.
+ * The identifier to score — a phone number or email address.
*/
- dispatch_id?: string;
+ target: Shared.Target;
/**
- * The metadata for this prediction.
+ * Values for the attributes the flow's recipes declare, keyed without the `attr.`
+ * namespace a rule uses to reference them.
+ *
+ * An attribute a recipe declares and this request omits is treated as missing
+ * evidence, not as an empty value: the rules reading it report `NOT_EVALUATED`
+ * rather than being scored as though the condition were false. A key no recipe in
+ * the flow declares is ignored rather than rejected, so one payload can serve
+ * flows that read different attributes.
*/
- metadata?: WatchPredictParams.Metadata;
+ attributes?: { [key: string]: string };
+
+ /**
+ * The identifier of the dispatch that came from the front-end SDK. Signals it
+ * carries fill in anything the request did not state; the request wins where both
+ * supply a value.
+ */
+ dispatch_id?: string;
/**
* The signals used for anti-fraud. For more details, refer to
* [Signals](/verify/v2/documentation/prevent-fraud#signals).
*/
- signals?: WatchPredictParams.Signals;
+ signals?: Shared.Signals;
}
-export namespace WatchPredictParams {
+export interface WatchPredictParams {
/**
* The signup identifier to score — a phone number or email address.
*/
- export interface Target {
- /**
- * The type of the target. Either "phone_number" or "email_address".
- */
- type: 'phone_number' | 'email_address';
+ target: Shared.Target;
- /**
- * An E.164 formatted phone number or an email address.
- */
- value: string;
- }
+ /**
+ * The identifier of the dispatch that came from the front-end SDK.
+ */
+ dispatch_id?: string;
/**
* The metadata for this prediction.
*/
- export interface Metadata {
- /**
- * A user-defined identifier to correlate this prediction with. It is returned in
- * the response and any webhook events that refer to this prediction.
- */
- correlation_id?: string;
- }
+ metadata?: WatchPredictParams.Metadata;
/**
* The signals used for anti-fraud. For more details, refer to
* [Signals](/verify/v2/documentation/prevent-fraud#signals).
*/
- export interface Signals {
- /**
- * The version of your application.
- */
- app_version?: string;
-
- /**
- * A unique ID for the user's device. You should ensure that each user device has a
- * unique `device_id` value. Ideally, for Android, this corresponds to the
- * `ANDROID_ID` and for iOS, this corresponds to the `identifierForVendor`.
- */
- device_id?: string;
-
- /**
- * The model of the user's device.
- */
- device_model?: string;
-
- /**
- * The type of the user's device.
- */
- device_platform?: 'android' | 'ios' | 'ipados' | 'tvos' | 'web';
-
- /**
- * Whether the end-user already exists in your system, for example an existing
- * account signing in again rather than a first-time signup. Unlike
- * `is_trusted_user`, this signal does not bypass fraud checks; it is taken into
- * account as one additional anti-fraud signal. For more details, refer to
- * [Signals](/verify/v2/documentation/prevent-fraud#signals).
- */
- existing_user?: boolean;
-
- /**
- * The public IP v4 or v6 address of the end-user's device. You should collect this
- * from your backend. If your backend is behind a proxy, use the `X-Forwarded-For`,
- * `Forwarded`, `True-Client-IP`, `CF-Connecting-IP` or an equivalent header to get
- * the actual public IP of the end-user's device.
- */
- ip?: string;
-
- /**
- * This signal should indicate a higher level of trust, explicitly stating that the
- * user is genuine. Contact us to discuss your use case. For more details, refer to
- * [Signals](/verify/v2/documentation/prevent-fraud#signals).
- */
- is_trusted_user?: boolean;
-
- /**
- * The JA4 fingerprint observed for the end-user's connection. Prelude will infer
- * it automatically when you use our Frontend SDKs (which use Prelude's edge
- * network), but you can also forward the value if you terminate TLS yourself.
- */
- ja4_fingerprint?: string;
-
- /**
- * The version of the user's device operating system.
- */
- os_version?: string;
+ signals?: Shared.Signals;
+}
+export namespace WatchPredictParams {
+ /**
+ * The metadata for this prediction.
+ */
+ export interface Metadata {
/**
- * The user agent of the user's device. If the individual fields (os_version,
- * device_platform, device_model) are provided, we will prioritize those values
- * instead of parsing them from the user agent string.
+ * A user-defined identifier to correlate this prediction with. It is returned in
+ * the response and any webhook events that refer to this prediction.
*/
- user_agent?: string;
+ correlation_id?: string;
}
}
@@ -328,24 +435,7 @@ export namespace WatchSendEventsParams {
/**
* The event target. Only supports phone numbers for now.
*/
- target: Event.Target;
- }
-
- export namespace Event {
- /**
- * The event target. Only supports phone numbers for now.
- */
- export interface Target {
- /**
- * The type of the target. Either "phone_number" or "email_address".
- */
- type: 'phone_number' | 'email_address';
-
- /**
- * An E.164 formatted phone number or an email address.
- */
- value: string;
- }
+ target: Shared.Target;
}
}
@@ -362,7 +452,7 @@ export namespace WatchSendFeedbacksParams {
/**
* The feedback target. Only supports phone numbers for now.
*/
- target: Feedback.Target;
+ target: Shared.Target;
/**
* The type of feedback.
@@ -376,21 +466,6 @@ export namespace WatchSendFeedbacksParams {
}
export namespace Feedback {
- /**
- * The feedback target. Only supports phone numbers for now.
- */
- export interface Target {
- /**
- * The type of the target. Either "phone_number" or "email_address".
- */
- type: 'phone_number' | 'email_address';
-
- /**
- * An E.164 formatted phone number or an email address.
- */
- value: string;
- }
-
/**
* The metadata for this feedback.
*/
@@ -406,9 +481,11 @@ export namespace WatchSendFeedbacksParams {
export declare namespace Watch {
export {
+ type WatchEvaluateResponse as WatchEvaluateResponse,
type WatchPredictResponse as WatchPredictResponse,
type WatchSendEventsResponse as WatchSendEventsResponse,
type WatchSendFeedbacksResponse as WatchSendFeedbacksResponse,
+ type WatchEvaluateParams as WatchEvaluateParams,
type WatchPredictParams as WatchPredictParams,
type WatchSendEventsParams as WatchSendEventsParams,
type WatchSendFeedbacksParams as WatchSendFeedbacksParams,
diff --git a/tests/api-resources/intel/kyc.test.ts b/tests/api-resources/intel/kyc.test.ts
new file mode 100644
index 0000000..1d51a6c
--- /dev/null
+++ b/tests/api-resources/intel/kyc.test.ts
@@ -0,0 +1,22 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import Prelude from '@prelude.so/sdk';
+import { Response } from 'node-fetch';
+
+const client = new Prelude({
+ apiToken: 'My API Token',
+ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
+});
+
+describe('resource kyc', () => {
+ test('match', async () => {
+ const responsePromise = client.intel.kyc.match('+12065550100', {});
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+});
diff --git a/tests/api-resources/notify.test.ts b/tests/api-resources/notify.test.ts
index efe5754..61734e2 100644
--- a/tests/api-resources/notify.test.ts
+++ b/tests/api-resources/notify.test.ts
@@ -140,6 +140,31 @@ describe('resource notify', () => {
).rejects.toThrow(Prelude.NotFoundError);
});
+ test('reply: only required params', async () => {
+ const responsePromise = client.notify.reply({
+ reply_to: 'im_01k8aq2zggeyssvt53zgvpx63a',
+ text: "Thanks for reaching out! We'll look into your request.",
+ to: '+33612345678',
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('reply: required and optional params', async () => {
+ const response = await client.notify.reply({
+ reply_to: 'im_01k8aq2zggeyssvt53zgvpx63a',
+ text: "Thanks for reaching out! We'll look into your request.",
+ to: '+33612345678',
+ callback_url: 'https://your-app.com/webhooks/notify',
+ correlation_id: 'support-ticket-42',
+ });
+ });
+
test('send: only required params', async () => {
const responsePromise = client.notify.send({
template_id: 'template_01k8ap1btqf5r9fq2c8ax5fhc9',
diff --git a/tests/api-resources/verification-management/sandbox.test.ts b/tests/api-resources/verification-management/sandbox.test.ts
new file mode 100644
index 0000000..69fa48c
--- /dev/null
+++ b/tests/api-resources/verification-management/sandbox.test.ts
@@ -0,0 +1,70 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import Prelude from '@prelude.so/sdk';
+import { Response } from 'node-fetch';
+
+const client = new Prelude({
+ apiToken: 'My API Token',
+ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
+});
+
+describe('resource sandbox', () => {
+ test('addPhoneNumber: only required params', async () => {
+ const responsePromise = client.verificationManagement.sandbox.addPhoneNumber({
+ attempt_code: '123456',
+ phone_number: '+30123456789',
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('addPhoneNumber: required and optional params', async () => {
+ const response = await client.verificationManagement.sandbox.addPhoneNumber({
+ attempt_code: '123456',
+ phone_number: '+30123456789',
+ });
+ });
+
+ test('deletePhoneNumber', async () => {
+ const responsePromise = client.verificationManagement.sandbox.deletePhoneNumber('+12065550100');
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('deletePhoneNumber: request options instead of params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(
+ client.verificationManagement.sandbox.deletePhoneNumber('+12065550100', {
+ path: '/_stainless_unknown_path',
+ }),
+ ).rejects.toThrow(Prelude.NotFoundError);
+ });
+
+ test('listPhoneNumbers', async () => {
+ const responsePromise = client.verificationManagement.sandbox.listPhoneNumbers();
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('listPhoneNumbers: request options instead of params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(
+ client.verificationManagement.sandbox.listPhoneNumbers({ path: '/_stainless_unknown_path' }),
+ ).rejects.toThrow(Prelude.NotFoundError);
+ });
+});
diff --git a/tests/api-resources/verification-management.test.ts b/tests/api-resources/verification-management/verification-management.test.ts
similarity index 100%
rename from tests/api-resources/verification-management.test.ts
rename to tests/api-resources/verification-management/verification-management.test.ts
diff --git a/tests/api-resources/verification/phone/history.test.ts b/tests/api-resources/verification/phone/history.test.ts
new file mode 100644
index 0000000..5d989f5
--- /dev/null
+++ b/tests/api-resources/verification/phone/history.test.ts
@@ -0,0 +1,72 @@
+// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
+
+import Prelude from '@prelude.so/sdk';
+import { Response } from 'node-fetch';
+
+const client = new Prelude({
+ apiToken: 'My API Token',
+ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010',
+});
+
+describe('resource history', () => {
+ test('retrieve', async () => {
+ const responsePromise = client.verification.phone.history.retrieve('vrf_01jc0t6fwwfgfsq1md24mhyztj');
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('retrieve: request options instead of params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(
+ client.verification.phone.history.retrieve('vrf_01jc0t6fwwfgfsq1md24mhyztj', {
+ path: '/_stainless_unknown_path',
+ }),
+ ).rejects.toThrow(Prelude.NotFoundError);
+ });
+
+ test('list', async () => {
+ const responsePromise = client.verification.phone.history.list();
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('list: request options instead of params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(
+ client.verification.phone.history.list({ path: '/_stainless_unknown_path' }),
+ ).rejects.toThrow(Prelude.NotFoundError);
+ });
+
+ test('list: request options and params are passed correctly', async () => {
+ // ensure the request options are being passed correctly by passing an invalid HTTP method in order to cause an error
+ await expect(
+ client.verification.phone.history.list(
+ {
+ channels: ['sms'],
+ cursor: 'cursor',
+ device_platform: 'android',
+ from: '2026-09-01T00:00:00Z',
+ limit: 1,
+ max_attempts: 0,
+ min_attempts: 0,
+ phone_number: '+33612345678',
+ region: 'FR',
+ status: 'converted',
+ template_id: 'template_01jc0t6fwwfgfsq1md24mhyztj',
+ to: '2026-09-08T00:00:00Z',
+ },
+ { path: '/_stainless_unknown_path' },
+ ),
+ ).rejects.toThrow(Prelude.NotFoundError);
+ });
+});
diff --git a/tests/api-resources/verification.test.ts b/tests/api-resources/verification/verification.test.ts
similarity index 100%
rename from tests/api-resources/verification.test.ts
rename to tests/api-resources/verification/verification.test.ts
diff --git a/tests/api-resources/watch.test.ts b/tests/api-resources/watch.test.ts
index db4afe7..195dba5 100644
--- a/tests/api-resources/watch.test.ts
+++ b/tests/api-resources/watch.test.ts
@@ -9,6 +9,42 @@ const client = new Prelude({
});
describe('resource watch', () => {
+ test('evaluate: only required params', async () => {
+ const responsePromise = client.watch.evaluate({
+ flow_id: 'flo_01jc0t6fwwfgfsq1md24mhyztj',
+ target: { type: 'phone_number', value: '+30123456789' },
+ });
+ const rawResponse = await responsePromise.asResponse();
+ expect(rawResponse).toBeInstanceOf(Response);
+ const response = await responsePromise;
+ expect(response).not.toBeInstanceOf(Response);
+ const dataAndResponse = await responsePromise.withResponse();
+ expect(dataAndResponse.data).toBe(response);
+ expect(dataAndResponse.response).toBe(rawResponse);
+ });
+
+ test('evaluate: required and optional params', async () => {
+ const response = await client.watch.evaluate({
+ flow_id: 'flo_01jc0t6fwwfgfsq1md24mhyztj',
+ target: { type: 'phone_number', value: '+30123456789' },
+ attributes: { plan_tier: 'free', account_age_days: '3' },
+ dispatch_id: '123e4567-e89b-12d3-a456-426614174000',
+ signals: {
+ app_version: '1.2.34',
+ device_id: '8F0B8FDD-C2CB-4387-B20A-56E9B2E5A0D2',
+ device_model: 'iPhone17,2',
+ device_platform: 'ios',
+ existing_user: false,
+ ip: '203.0.113.123',
+ is_trusted_user: false,
+ ja4_fingerprint: 't13d1516h2_8daaf6152771_e5627efa2ab1',
+ os_version: '18.0.1',
+ user_agent:
+ 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
+ },
+ });
+ });
+
test('predict: only required params', async () => {
const responsePromise = client.watch.predict({ target: { type: 'phone_number', value: '+30123456789' } });
const rawResponse = await responsePromise.asResponse();
From cec93b10df8de60c923cbe9ca68e195c17b5fff6 Mon Sep 17 00:00:00 2001
From: "stainless-app[bot]"
<142633134+stainless-app[bot]@users.noreply.github.com>
Date: Fri, 18 Sep 2026 15:49:11 +0000
Subject: [PATCH 2/2] release: 0.15.0
---
.release-please-manifest.json | 2 +-
CHANGELOG.md | 8 ++++++++
package.json | 2 +-
src/version.ts | 2 +-
4 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index 727e2be..f87262a 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.14.0"
+ ".": "0.15.0"
}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a78939e..7cc44ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,13 @@
# Changelog
+## 0.15.0 (2026-09-18)
+
+Full Changelog: [v0.14.0...v0.15.0](https://github.com/prelude-so/node-sdk/compare/v0.14.0...v0.15.0)
+
+### Features
+
+* **api:** manual updates ([524243a](https://github.com/prelude-so/node-sdk/commit/524243a641cfb439443592613422465cefd1f8d3))
+
## 0.14.0 (2026-09-15)
Full Changelog: [v0.13.0...v0.14.0](https://github.com/prelude-so/node-sdk/compare/v0.13.0...v0.14.0)
diff --git a/package.json b/package.json
index ccfa5ba..fe578ca 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@prelude.so/sdk",
- "version": "0.14.0",
+ "version": "0.15.0",
"description": "The official TypeScript library for the Prelude API",
"author": "Prelude ",
"types": "dist/index.d.ts",
diff --git a/src/version.ts b/src/version.ts
index e2b0672..b67001e 100644
--- a/src/version.ts
+++ b/src/version.ts
@@ -1 +1 @@
-export const VERSION = '0.14.0'; // x-release-please-version
+export const VERSION = '0.15.0'; // x-release-please-version