diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 8d0a116..4208b5c 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.4" + ".": "0.6.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 603f57a..e26d438 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 21 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-d9763d006969b49a1473851069fdfa429eb13133b64103a62963bb70ddb22305.yml -openapi_spec_hash: 6aee689b7a759b12c85c088c15e29bc0 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/cas-parser%2Fcas-parser-e5c0c65637cdf3a6c4360b8193973b73a3d35ad1056ef607c3319ef03e591a55.yml +openapi_spec_hash: 7515d1e5fe3130b9f5411f7aacbc8a64 config_hash: 5509bb7a961ae2e79114b24c381606d4 diff --git a/CHANGELOG.md b/CHANGELOG.md index c3d68b3..62fd0e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.6.0 (2026-04-19) + +Full Changelog: [v0.5.4...v0.6.0](https://github.com/CASParser/cas-parser-java/compare/v0.5.4...v0.6.0) + +### Features + +* **api:** api update ([cc71346](https://github.com/CASParser/cas-parser-java/commit/cc713467669ee9f6a2456ce9302b6485f0dfe434)) +* **api:** api update ([b6d20bb](https://github.com/CASParser/cas-parser-java/commit/b6d20bb4a78c9a8cf7328cb4336e2d4bf5375825)) + ## 0.5.4 (2026-03-25) Full Changelog: [v0.5.3...v0.5.4](https://github.com/CASParser/cas-parser-java/compare/v0.5.3...v0.5.4) diff --git a/README.md b/README.md index 2eca0b5..7e9b378 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ -[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.5.4) -[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.5.4/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.5.4) +[![Maven Central](https://img.shields.io/maven-central/v/com.cas_parser.api/cas-parser-java)](https://central.sonatype.com/artifact/com.cas_parser.api/cas-parser-java/0.6.0) +[![javadoc](https://javadoc.io/badge2/com.cas_parser.api/cas-parser-java/0.6.0/javadoc.svg)](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.6.0) @@ -22,7 +22,7 @@ Use the Cas Parser MCP Server to enable AI assistants to interact with this API, -The REST API documentation can be found on [casparser.in](https://casparser.in/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.5.4). +The REST API documentation can be found on [casparser.in](https://casparser.in/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/com.cas_parser.api/cas-parser-java/0.6.0). @@ -33,7 +33,7 @@ The REST API documentation can be found on [casparser.in](https://casparser.in/d ### Gradle ```kotlin -implementation("com.cas_parser.api:cas-parser-java:0.5.4") +implementation("com.cas_parser.api:cas-parser-java:0.6.0") ``` ### Maven @@ -42,7 +42,7 @@ implementation("com.cas_parser.api:cas-parser-java:0.5.4") com.cas_parser.api cas-parser-java - 0.5.4 + 0.6.0 ``` diff --git a/build.gradle.kts b/build.gradle.kts index bb21bd5..8f7d82f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ repositories { allprojects { group = "com.cas_parser.api" - version = "0.5.4" // x-release-please-version + version = "0.6.0" // x-release-please-version } subprojects { diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParams.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParams.kt index a20d52b..54b1e1c 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParams.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParams.kt @@ -9,7 +9,6 @@ import com.cas_parser.api.core.JsonMissing import com.cas_parser.api.core.JsonValue import com.cas_parser.api.core.Params import com.cas_parser.api.core.checkKnown -import com.cas_parser.api.core.checkRequired import com.cas_parser.api.core.http.Headers import com.cas_parser.api.core.http.QueryParams import com.cas_parser.api.core.toImmutable @@ -24,21 +23,14 @@ import java.util.Optional import kotlin.jvm.optionals.getOrNull /** - * Create a dedicated inbound email address for collecting CAS statements via email forwarding. + * Create a dedicated inbound email address for collecting CAS statements via email forwarding. When + * an investor forwards a CAS email to this address, we verify the sender and make the file + * available to you. * - * **How it works:** - * 1. Create an inbound email with your webhook URL - * 2. Display the email address to your user (e.g., "Forward your CAS to - * ie_xxx@import.casparser.in") - * 3. When an investor forwards a CAS email, we verify the sender and deliver to your webhook - * - * **Webhook Delivery:** - * - We POST to your `callback_url` with JSON body containing files (matching EmailCASFile schema) - * - Failed deliveries are retried automatically with exponential backoff - * - * **Inactivity:** - * - Inbound emails with no activity in 30 days are marked inactive - * - Active inbound emails remain operational indefinitely + * `callback_url` is **optional**: + * - **Set it** — we POST each parsed email to your webhook as it arrives. + * - **Omit it** — retrieve files via `GET /v4/inbound-email/{id}/files` without building a webhook + * consumer. */ class InboundEmailCreateParams private constructor( @@ -48,21 +40,9 @@ private constructor( ) : Params { /** - * Webhook URL where we POST email notifications. Must be HTTPS in production (HTTP allowed for - * localhost during development). - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun callbackUrl(): String = body.callbackUrl() - - /** - * Optional custom email prefix for user-friendly addresses. - * - Must be 3-32 characters - * - Alphanumeric + hyphens only - * - Must start and end with letter/number - * - Example: `john-portfolio@import.casparser.in` - * - If omitted, generates random ID like `ie_abc123xyz@import.casparser.in` + * Optional custom email prefix (e.g. `john-portfolio@import.casparser.in`). 3-32 chars, + * alphanumeric + hyphens, must start/end with a letter or number. If omitted, a random ID is + * generated. * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -81,6 +61,15 @@ private constructor( */ fun allowedSources(): Optional> = body.allowedSources() + /** + * Optional webhook URL where we POST parsed emails. Must be HTTPS in production (HTTP allowed + * for localhost). If omitted, retrieve files via `GET /v4/inbound-email/{id}/files`. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the + * server responded with an unexpected value). + */ + fun callbackUrl(): Optional = body.callbackUrl() + /** * Optional key-value pairs (max 10) to include in webhook payload. Useful for passing context * like plan_type, campaign_id, etc. @@ -99,13 +88,6 @@ private constructor( */ fun reference(): Optional = body.reference() - /** - * Returns the raw JSON value of [callbackUrl]. - * - * Unlike [callbackUrl], this method doesn't throw if the JSON field has an unexpected type. - */ - fun _callbackUrl(): JsonField = body._callbackUrl() - /** * Returns the raw JSON value of [alias]. * @@ -120,6 +102,13 @@ private constructor( */ fun _allowedSources(): JsonField> = body._allowedSources() + /** + * Returns the raw JSON value of [callbackUrl]. + * + * Unlike [callbackUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + fun _callbackUrl(): JsonField = body._callbackUrl() + /** * Returns the raw JSON value of [metadata]. * @@ -146,14 +135,9 @@ private constructor( companion object { - /** - * Returns a mutable builder for constructing an instance of [InboundEmailCreateParams]. - * - * The following fields are required: - * ```java - * .callbackUrl() - * ``` - */ + @JvmStatic fun none(): InboundEmailCreateParams = builder().build() + + /** Returns a mutable builder for constructing an instance of [InboundEmailCreateParams]. */ @JvmStatic fun builder() = Builder() } @@ -176,9 +160,9 @@ private constructor( * * This is generally only useful if you are already constructing the body separately. * Otherwise, it's more convenient to use the top-level setters instead: - * - [callbackUrl] * - [alias] * - [allowedSources] + * - [callbackUrl] * - [metadata] * - [reference] * - etc. @@ -186,27 +170,9 @@ private constructor( fun body(body: Body) = apply { this.body = body.toBuilder() } /** - * Webhook URL where we POST email notifications. Must be HTTPS in production (HTTP allowed - * for localhost during development). - */ - fun callbackUrl(callbackUrl: String) = apply { body.callbackUrl(callbackUrl) } - - /** - * Sets [Builder.callbackUrl] to an arbitrary JSON value. - * - * You should usually call [Builder.callbackUrl] with a well-typed [String] value instead. - * This method is primarily for setting the field to an undocumented or not yet supported - * value. - */ - fun callbackUrl(callbackUrl: JsonField) = apply { body.callbackUrl(callbackUrl) } - - /** - * Optional custom email prefix for user-friendly addresses. - * - Must be 3-32 characters - * - Alphanumeric + hyphens only - * - Must start and end with letter/number - * - Example: `john-portfolio@import.casparser.in` - * - If omitted, generates random ID like `ie_abc123xyz@import.casparser.in` + * Optional custom email prefix (e.g. `john-portfolio@import.casparser.in`). 3-32 chars, + * alphanumeric + hyphens, must start/end with a letter or number. If omitted, a random ID + * is generated. */ fun alias(alias: String) = apply { body.alias(alias) } @@ -249,6 +215,25 @@ private constructor( body.addAllowedSource(allowedSource) } + /** + * Optional webhook URL where we POST parsed emails. Must be HTTPS in production (HTTP + * allowed for localhost). If omitted, retrieve files via `GET + * /v4/inbound-email/{id}/files`. + */ + fun callbackUrl(callbackUrl: String?) = apply { body.callbackUrl(callbackUrl) } + + /** Alias for calling [Builder.callbackUrl] with `callbackUrl.orElse(null)`. */ + fun callbackUrl(callbackUrl: Optional) = callbackUrl(callbackUrl.getOrNull()) + + /** + * Sets [Builder.callbackUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.callbackUrl] with a well-typed [String] value instead. + * This method is primarily for setting the field to an undocumented or not yet supported + * value. + */ + fun callbackUrl(callbackUrl: JsonField) = apply { body.callbackUrl(callbackUrl) } + /** * Optional key-value pairs (max 10) to include in webhook payload. Useful for passing * context like plan_type, campaign_id, etc. @@ -400,13 +385,6 @@ private constructor( * Returns an immutable instance of [InboundEmailCreateParams]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .callbackUrl() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): InboundEmailCreateParams = InboundEmailCreateParams( @@ -425,9 +403,9 @@ private constructor( class Body @JsonCreator(mode = JsonCreator.Mode.DISABLED) private constructor( - private val callbackUrl: JsonField, private val alias: JsonField, private val allowedSources: JsonField>, + private val callbackUrl: JsonField, private val metadata: JsonField, private val reference: JsonField, private val additionalProperties: MutableMap, @@ -435,37 +413,25 @@ private constructor( @JsonCreator private constructor( - @JsonProperty("callback_url") - @ExcludeMissing - callbackUrl: JsonField = JsonMissing.of(), @JsonProperty("alias") @ExcludeMissing alias: JsonField = JsonMissing.of(), @JsonProperty("allowed_sources") @ExcludeMissing allowedSources: JsonField> = JsonMissing.of(), + @JsonProperty("callback_url") + @ExcludeMissing + callbackUrl: JsonField = JsonMissing.of(), @JsonProperty("metadata") @ExcludeMissing metadata: JsonField = JsonMissing.of(), @JsonProperty("reference") @ExcludeMissing reference: JsonField = JsonMissing.of(), - ) : this(callbackUrl, alias, allowedSources, metadata, reference, mutableMapOf()) + ) : this(alias, allowedSources, callbackUrl, metadata, reference, mutableMapOf()) /** - * Webhook URL where we POST email notifications. Must be HTTPS in production (HTTP allowed - * for localhost during development). - * - * @throws CasParserInvalidDataException if the JSON field has an unexpected type or is - * unexpectedly missing or null (e.g. if the server responded with an unexpected value). - */ - fun callbackUrl(): String = callbackUrl.getRequired("callback_url") - - /** - * Optional custom email prefix for user-friendly addresses. - * - Must be 3-32 characters - * - Alphanumeric + hyphens only - * - Must start and end with letter/number - * - Example: `john-portfolio@import.casparser.in` - * - If omitted, generates random ID like `ie_abc123xyz@import.casparser.in` + * Optional custom email prefix (e.g. `john-portfolio@import.casparser.in`). 3-32 chars, + * alphanumeric + hyphens, must start/end with a letter or number. If omitted, a random ID + * is generated. * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -485,6 +451,16 @@ private constructor( fun allowedSources(): Optional> = allowedSources.getOptional("allowed_sources") + /** + * Optional webhook URL where we POST parsed emails. Must be HTTPS in production (HTTP + * allowed for localhost). If omitted, retrieve files via `GET + * /v4/inbound-email/{id}/files`. + * + * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if + * the server responded with an unexpected value). + */ + fun callbackUrl(): Optional = callbackUrl.getOptional("callback_url") + /** * Optional key-value pairs (max 10) to include in webhook payload. Useful for passing * context like plan_type, campaign_id, etc. @@ -503,15 +479,6 @@ private constructor( */ fun reference(): Optional = reference.getOptional("reference") - /** - * Returns the raw JSON value of [callbackUrl]. - * - * Unlike [callbackUrl], this method doesn't throw if the JSON field has an unexpected type. - */ - @JsonProperty("callback_url") - @ExcludeMissing - fun _callbackUrl(): JsonField = callbackUrl - /** * Returns the raw JSON value of [alias]. * @@ -529,6 +496,15 @@ private constructor( @ExcludeMissing fun _allowedSources(): JsonField> = allowedSources + /** + * Returns the raw JSON value of [callbackUrl]. + * + * Unlike [callbackUrl], this method doesn't throw if the JSON field has an unexpected type. + */ + @JsonProperty("callback_url") + @ExcludeMissing + fun _callbackUrl(): JsonField = callbackUrl + /** * Returns the raw JSON value of [metadata]. * @@ -557,61 +533,34 @@ private constructor( companion object { - /** - * Returns a mutable builder for constructing an instance of [Body]. - * - * The following fields are required: - * ```java - * .callbackUrl() - * ``` - */ + /** Returns a mutable builder for constructing an instance of [Body]. */ @JvmStatic fun builder() = Builder() } /** A builder for [Body]. */ class Builder internal constructor() { - private var callbackUrl: JsonField? = null private var alias: JsonField = JsonMissing.of() private var allowedSources: JsonField>? = null + private var callbackUrl: JsonField = JsonMissing.of() private var metadata: JsonField = JsonMissing.of() private var reference: JsonField = JsonMissing.of() private var additionalProperties: MutableMap = mutableMapOf() @JvmSynthetic internal fun from(body: Body) = apply { - callbackUrl = body.callbackUrl alias = body.alias allowedSources = body.allowedSources.map { it.toMutableList() } + callbackUrl = body.callbackUrl metadata = body.metadata reference = body.reference additionalProperties = body.additionalProperties.toMutableMap() } /** - * Webhook URL where we POST email notifications. Must be HTTPS in production (HTTP - * allowed for localhost during development). - */ - fun callbackUrl(callbackUrl: String) = callbackUrl(JsonField.of(callbackUrl)) - - /** - * Sets [Builder.callbackUrl] to an arbitrary JSON value. - * - * You should usually call [Builder.callbackUrl] with a well-typed [String] value - * instead. This method is primarily for setting the field to an undocumented or not yet - * supported value. - */ - fun callbackUrl(callbackUrl: JsonField) = apply { - this.callbackUrl = callbackUrl - } - - /** - * Optional custom email prefix for user-friendly addresses. - * - Must be 3-32 characters - * - Alphanumeric + hyphens only - * - Must start and end with letter/number - * - Example: `john-portfolio@import.casparser.in` - * - If omitted, generates random ID like `ie_abc123xyz@import.casparser.in` + * Optional custom email prefix (e.g. `john-portfolio@import.casparser.in`). 3-32 chars, + * alphanumeric + hyphens, must start/end with a letter or number. If omitted, a random + * ID is generated. */ fun alias(alias: String) = alias(JsonField.of(alias)) @@ -657,6 +606,27 @@ private constructor( } } + /** + * Optional webhook URL where we POST parsed emails. Must be HTTPS in production (HTTP + * allowed for localhost). If omitted, retrieve files via `GET + * /v4/inbound-email/{id}/files`. + */ + fun callbackUrl(callbackUrl: String?) = callbackUrl(JsonField.ofNullable(callbackUrl)) + + /** Alias for calling [Builder.callbackUrl] with `callbackUrl.orElse(null)`. */ + fun callbackUrl(callbackUrl: Optional) = callbackUrl(callbackUrl.getOrNull()) + + /** + * Sets [Builder.callbackUrl] to an arbitrary JSON value. + * + * You should usually call [Builder.callbackUrl] with a well-typed [String] value + * instead. This method is primarily for setting the field to an undocumented or not yet + * supported value. + */ + fun callbackUrl(callbackUrl: JsonField) = apply { + this.callbackUrl = callbackUrl + } + /** * Optional key-value pairs (max 10) to include in webhook payload. Useful for passing * context like plan_type, campaign_id, etc. @@ -710,19 +680,12 @@ private constructor( * Returns an immutable instance of [Body]. * * Further updates to this [Builder] will not mutate the returned instance. - * - * The following fields are required: - * ```java - * .callbackUrl() - * ``` - * - * @throws IllegalStateException if any required field is unset. */ fun build(): Body = Body( - checkRequired("callbackUrl", callbackUrl), alias, (allowedSources ?: JsonMissing.of()).map { it.toImmutable() }, + callbackUrl, metadata, reference, additionalProperties.toMutableMap(), @@ -736,9 +699,9 @@ private constructor( return@apply } - callbackUrl() alias() allowedSources().ifPresent { it.forEach { it.validate() } } + callbackUrl() metadata().ifPresent { it.validate() } reference() validated = true @@ -760,9 +723,9 @@ private constructor( */ @JvmSynthetic internal fun validity(): Int = - (if (callbackUrl.asKnown().isPresent) 1 else 0) + - (if (alias.asKnown().isPresent) 1 else 0) + + (if (alias.asKnown().isPresent) 1 else 0) + (allowedSources.asKnown().getOrNull()?.sumOf { it.validity().toInt() } ?: 0) + + (if (callbackUrl.asKnown().isPresent) 1 else 0) + (metadata.asKnown().getOrNull()?.validity() ?: 0) + (if (reference.asKnown().isPresent) 1 else 0) @@ -772,9 +735,9 @@ private constructor( } return other is Body && - callbackUrl == other.callbackUrl && alias == other.alias && allowedSources == other.allowedSources && + callbackUrl == other.callbackUrl && metadata == other.metadata && reference == other.reference && additionalProperties == other.additionalProperties @@ -782,9 +745,9 @@ private constructor( private val hashCode: Int by lazy { Objects.hash( - callbackUrl, alias, allowedSources, + callbackUrl, metadata, reference, additionalProperties, @@ -794,7 +757,7 @@ private constructor( override fun hashCode(): Int = hashCode override fun toString() = - "Body{callbackUrl=$callbackUrl, alias=$alias, allowedSources=$allowedSources, metadata=$metadata, reference=$reference, additionalProperties=$additionalProperties}" + "Body{alias=$alias, allowedSources=$allowedSources, callbackUrl=$callbackUrl, metadata=$metadata, reference=$reference, additionalProperties=$additionalProperties}" } class AllowedSource @JsonCreator private constructor(private val value: JsonField) : diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateResponse.kt index fb3d9d5..90aaaf9 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateResponse.kt @@ -80,7 +80,8 @@ private constructor( allowedSources.getOptional("allowed_sources") /** - * Webhook URL for email notifications + * Webhook URL for email notifications. `null` means files are only retrievable via `GET + * /v4/inbound-email/{id}/files` (pull delivery). * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -291,8 +292,14 @@ private constructor( } } - /** Webhook URL for email notifications */ - fun callbackUrl(callbackUrl: String) = callbackUrl(JsonField.of(callbackUrl)) + /** + * Webhook URL for email notifications. `null` means files are only retrievable via `GET + * /v4/inbound-email/{id}/files` (pull delivery). + */ + fun callbackUrl(callbackUrl: String?) = callbackUrl(JsonField.ofNullable(callbackUrl)) + + /** Alias for calling [Builder.callbackUrl] with `callbackUrl.orElse(null)`. */ + fun callbackUrl(callbackUrl: Optional) = callbackUrl(callbackUrl.getOrNull()) /** * Sets [Builder.callbackUrl] to an arbitrary JSON value. diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailListResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailListResponse.kt index 12c0e54..0412e52 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailListResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailListResponse.kt @@ -351,7 +351,8 @@ private constructor( allowedSources.getOptional("allowed_sources") /** - * Webhook URL for email notifications + * Webhook URL for email notifications. `null` means files are only retrievable via `GET + * /v4/inbound-email/{id}/files` (pull delivery). * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if * the server responded with an unexpected value). @@ -562,8 +563,14 @@ private constructor( } } - /** Webhook URL for email notifications */ - fun callbackUrl(callbackUrl: String) = callbackUrl(JsonField.of(callbackUrl)) + /** + * Webhook URL for email notifications. `null` means files are only retrievable via `GET + * /v4/inbound-email/{id}/files` (pull delivery). + */ + fun callbackUrl(callbackUrl: String?) = callbackUrl(JsonField.ofNullable(callbackUrl)) + + /** Alias for calling [Builder.callbackUrl] with `callbackUrl.orElse(null)`. */ + fun callbackUrl(callbackUrl: Optional) = callbackUrl(callbackUrl.getOrNull()) /** * Sets [Builder.callbackUrl] to an arbitrary JSON value. diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveResponse.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveResponse.kt index c997bf9..39aad18 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveResponse.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveResponse.kt @@ -80,7 +80,8 @@ private constructor( allowedSources.getOptional("allowed_sources") /** - * Webhook URL for email notifications + * Webhook URL for email notifications. `null` means files are only retrievable via `GET + * /v4/inbound-email/{id}/files` (pull delivery). * * @throws CasParserInvalidDataException if the JSON field has an unexpected type (e.g. if the * server responded with an unexpected value). @@ -291,8 +292,14 @@ private constructor( } } - /** Webhook URL for email notifications */ - fun callbackUrl(callbackUrl: String) = callbackUrl(JsonField.of(callbackUrl)) + /** + * Webhook URL for email notifications. `null` means files are only retrievable via `GET + * /v4/inbound-email/{id}/files` (pull delivery). + */ + fun callbackUrl(callbackUrl: String?) = callbackUrl(JsonField.ofNullable(callbackUrl)) + + /** Alias for calling [Builder.callbackUrl] with `callbackUrl.orElse(null)`. */ + fun callbackUrl(callbackUrl: Optional) = callbackUrl(callbackUrl.getOrNull()) /** * Sets [Builder.callbackUrl] to an arbitrary JSON value. diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsync.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsync.kt index 2c1b443..70d732d 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsync.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsync.kt @@ -55,31 +55,32 @@ interface InboundEmailServiceAsync { /** * Create a dedicated inbound email address for collecting CAS statements via email forwarding. + * When an investor forwards a CAS email to this address, we verify the sender and make the file + * available to you. * - * **How it works:** - * 1. Create an inbound email with your webhook URL - * 2. Display the email address to your user (e.g., "Forward your CAS to - * ie_xxx@import.casparser.in") - * 3. When an investor forwards a CAS email, we verify the sender and deliver to your webhook - * - * **Webhook Delivery:** - * - We POST to your `callback_url` with JSON body containing files (matching EmailCASFile - * schema) - * - Failed deliveries are retried automatically with exponential backoff - * - * **Inactivity:** - * - Inbound emails with no activity in 30 days are marked inactive - * - Active inbound emails remain operational indefinitely + * `callback_url` is **optional**: + * - **Set it** — we POST each parsed email to your webhook as it arrives. + * - **Omit it** — retrieve files via `GET /v4/inbound-email/{id}/files` without building a + * webhook consumer. */ - fun create(params: InboundEmailCreateParams): CompletableFuture = - create(params, RequestOptions.none()) + fun create(): CompletableFuture = + create(InboundEmailCreateParams.none()) /** @see create */ fun create( - params: InboundEmailCreateParams, + params: InboundEmailCreateParams = InboundEmailCreateParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): CompletableFuture + /** @see create */ + fun create( + params: InboundEmailCreateParams = InboundEmailCreateParams.none() + ): CompletableFuture = create(params, RequestOptions.none()) + + /** @see create */ + fun create(requestOptions: RequestOptions): CompletableFuture = + create(InboundEmailCreateParams.none(), requestOptions) + /** Retrieve details of a specific mailbox including statistics. */ fun retrieve(inboundEmailId: String): CompletableFuture = retrieve(inboundEmailId, InboundEmailRetrieveParams.none()) @@ -198,16 +199,26 @@ interface InboundEmailServiceAsync { * Returns a raw HTTP response for `post /v4/inbound-email`, but is otherwise the same as * [InboundEmailServiceAsync.create]. */ + fun create(): CompletableFuture> = + create(InboundEmailCreateParams.none()) + + /** @see create */ fun create( - params: InboundEmailCreateParams + params: InboundEmailCreateParams = InboundEmailCreateParams.none(), + requestOptions: RequestOptions = RequestOptions.none(), + ): CompletableFuture> + + /** @see create */ + fun create( + params: InboundEmailCreateParams = InboundEmailCreateParams.none() ): CompletableFuture> = create(params, RequestOptions.none()) /** @see create */ fun create( - params: InboundEmailCreateParams, - requestOptions: RequestOptions = RequestOptions.none(), - ): CompletableFuture> + requestOptions: RequestOptions + ): CompletableFuture> = + create(InboundEmailCreateParams.none(), requestOptions) /** * Returns a raw HTTP response for `get /v4/inbound-email/{inbound_email_id}`, but is diff --git a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/InboundEmailService.kt b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/InboundEmailService.kt index be0ff40..6b52989 100644 --- a/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/InboundEmailService.kt +++ b/cas-parser-java-core/src/main/kotlin/com/cas_parser/api/services/blocking/InboundEmailService.kt @@ -55,31 +55,31 @@ interface InboundEmailService { /** * Create a dedicated inbound email address for collecting CAS statements via email forwarding. + * When an investor forwards a CAS email to this address, we verify the sender and make the file + * available to you. * - * **How it works:** - * 1. Create an inbound email with your webhook URL - * 2. Display the email address to your user (e.g., "Forward your CAS to - * ie_xxx@import.casparser.in") - * 3. When an investor forwards a CAS email, we verify the sender and deliver to your webhook - * - * **Webhook Delivery:** - * - We POST to your `callback_url` with JSON body containing files (matching EmailCASFile - * schema) - * - Failed deliveries are retried automatically with exponential backoff - * - * **Inactivity:** - * - Inbound emails with no activity in 30 days are marked inactive - * - Active inbound emails remain operational indefinitely + * `callback_url` is **optional**: + * - **Set it** — we POST each parsed email to your webhook as it arrives. + * - **Omit it** — retrieve files via `GET /v4/inbound-email/{id}/files` without building a + * webhook consumer. */ - fun create(params: InboundEmailCreateParams): InboundEmailCreateResponse = - create(params, RequestOptions.none()) + fun create(): InboundEmailCreateResponse = create(InboundEmailCreateParams.none()) /** @see create */ fun create( - params: InboundEmailCreateParams, + params: InboundEmailCreateParams = InboundEmailCreateParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): InboundEmailCreateResponse + /** @see create */ + fun create( + params: InboundEmailCreateParams = InboundEmailCreateParams.none() + ): InboundEmailCreateResponse = create(params, RequestOptions.none()) + + /** @see create */ + fun create(requestOptions: RequestOptions): InboundEmailCreateResponse = + create(InboundEmailCreateParams.none(), requestOptions) + /** Retrieve details of a specific mailbox including statistics. */ fun retrieve(inboundEmailId: String): InboundEmailRetrieveResponse = retrieve(inboundEmailId, InboundEmailRetrieveParams.none()) @@ -192,16 +192,27 @@ interface InboundEmailService { * [InboundEmailService.create]. */ @MustBeClosed - fun create(params: InboundEmailCreateParams): HttpResponseFor = - create(params, RequestOptions.none()) + fun create(): HttpResponseFor = + create(InboundEmailCreateParams.none()) /** @see create */ @MustBeClosed fun create( - params: InboundEmailCreateParams, + params: InboundEmailCreateParams = InboundEmailCreateParams.none(), requestOptions: RequestOptions = RequestOptions.none(), ): HttpResponseFor + /** @see create */ + @MustBeClosed + fun create( + params: InboundEmailCreateParams = InboundEmailCreateParams.none() + ): HttpResponseFor = create(params, RequestOptions.none()) + + /** @see create */ + @MustBeClosed + fun create(requestOptions: RequestOptions): HttpResponseFor = + create(InboundEmailCreateParams.none(), requestOptions) + /** * Returns a raw HTTP response for `get /v4/inbound-email/{inbound_email_id}`, but is * otherwise the same as [InboundEmailService.retrieve]. diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParamsTest.kt index 900b778..876cff9 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParamsTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailCreateParamsTest.kt @@ -12,10 +12,10 @@ internal class InboundEmailCreateParamsTest { @Test fun create() { InboundEmailCreateParams.builder() - .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .alias("john-portfolio") .addAllowedSource(InboundEmailCreateParams.AllowedSource.CDSL) .addAllowedSource(InboundEmailCreateParams.AllowedSource.NSDL) + .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .metadata( InboundEmailCreateParams.Metadata.builder() .putAdditionalProperty("plan", JsonValue.from("premium")) @@ -30,10 +30,10 @@ internal class InboundEmailCreateParamsTest { fun body() { val params = InboundEmailCreateParams.builder() - .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .alias("john-portfolio") .addAllowedSource(InboundEmailCreateParams.AllowedSource.CDSL) .addAllowedSource(InboundEmailCreateParams.AllowedSource.NSDL) + .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .metadata( InboundEmailCreateParams.Metadata.builder() .putAdditionalProperty("plan", JsonValue.from("premium")) @@ -45,13 +45,13 @@ internal class InboundEmailCreateParamsTest { val body = params._body() - assertThat(body.callbackUrl()).isEqualTo("https://api.yourapp.com/webhooks/cas-email") assertThat(body.alias()).contains("john-portfolio") assertThat(body.allowedSources().getOrNull()) .containsExactly( InboundEmailCreateParams.AllowedSource.CDSL, InboundEmailCreateParams.AllowedSource.NSDL, ) + assertThat(body.callbackUrl()).contains("https://api.yourapp.com/webhooks/cas-email") assertThat(body.metadata()) .contains( InboundEmailCreateParams.Metadata.builder() @@ -64,13 +64,8 @@ internal class InboundEmailCreateParamsTest { @Test fun bodyWithoutOptionalFields() { - val params = - InboundEmailCreateParams.builder() - .callbackUrl("https://api.yourapp.com/webhooks/cas-email") - .build() + val params = InboundEmailCreateParams.builder().build() val body = params._body() - - assertThat(body.callbackUrl()).isEqualTo("https://api.yourapp.com/webhooks/cas-email") } } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveParamsTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveParamsTest.kt index 2b76fc3..8d7abc0 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveParamsTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/models/inboundemail/InboundEmailRetrieveParamsTest.kt @@ -9,14 +9,14 @@ internal class InboundEmailRetrieveParamsTest { @Test fun create() { - InboundEmailRetrieveParams.builder().inboundEmailId("ie_a1b2c3d4e5f6").build() + InboundEmailRetrieveParams.builder().inboundEmailId("inbound_email_id").build() } @Test fun pathParams() { - val params = InboundEmailRetrieveParams.builder().inboundEmailId("ie_a1b2c3d4e5f6").build() + val params = InboundEmailRetrieveParams.builder().inboundEmailId("inbound_email_id").build() - assertThat(params._pathParam(0)).isEqualTo("ie_a1b2c3d4e5f6") + assertThat(params._pathParam(0)).isEqualTo("inbound_email_id") // out-of-bound path param assertThat(params._pathParam(1)).isEqualTo("") } diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsyncTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsyncTest.kt index 0993dac..386e7ca 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsyncTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/async/InboundEmailServiceAsyncTest.kt @@ -20,10 +20,10 @@ internal class InboundEmailServiceAsyncTest { val inboundEmailFuture = inboundEmailServiceAsync.create( InboundEmailCreateParams.builder() - .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .alias("john-portfolio") .addAllowedSource(InboundEmailCreateParams.AllowedSource.CDSL) .addAllowedSource(InboundEmailCreateParams.AllowedSource.NSDL) + .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .metadata( InboundEmailCreateParams.Metadata.builder() .putAdditionalProperty("plan", JsonValue.from("premium")) @@ -44,7 +44,7 @@ internal class InboundEmailServiceAsyncTest { val client = CasParserOkHttpClientAsync.builder().apiKey("My API Key").build() val inboundEmailServiceAsync = client.inboundEmail() - val inboundEmailFuture = inboundEmailServiceAsync.retrieve("ie_a1b2c3d4e5f6") + val inboundEmailFuture = inboundEmailServiceAsync.retrieve("inbound_email_id") val inboundEmail = inboundEmailFuture.get() inboundEmail.validate() diff --git a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/InboundEmailServiceTest.kt b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/InboundEmailServiceTest.kt index 66d6b0c..8d826a9 100644 --- a/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/InboundEmailServiceTest.kt +++ b/cas-parser-java-core/src/test/kotlin/com/cas_parser/api/services/blocking/InboundEmailServiceTest.kt @@ -20,10 +20,10 @@ internal class InboundEmailServiceTest { val inboundEmail = inboundEmailService.create( InboundEmailCreateParams.builder() - .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .alias("john-portfolio") .addAllowedSource(InboundEmailCreateParams.AllowedSource.CDSL) .addAllowedSource(InboundEmailCreateParams.AllowedSource.NSDL) + .callbackUrl("https://api.yourapp.com/webhooks/cas-email") .metadata( InboundEmailCreateParams.Metadata.builder() .putAdditionalProperty("plan", JsonValue.from("premium")) @@ -43,7 +43,7 @@ internal class InboundEmailServiceTest { val client = CasParserOkHttpClient.builder().apiKey("My API Key").build() val inboundEmailService = client.inboundEmail() - val inboundEmail = inboundEmailService.retrieve("ie_a1b2c3d4e5f6") + val inboundEmail = inboundEmailService.retrieve("inbound_email_id") inboundEmail.validate() }