From 18415899d058342f93fe319dd14b2f0ae13c2985 Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Sat, 3 Oct 2026 13:47:06 +0200 Subject: [PATCH 1/6] fix(webhooks): accept future timestamps within tolerance Reject only when |now - timestamp| exceeds the tolerance, so small clock skew between Lettermint and the receiver no longer fails every webhook. --- .../java/co/lettermint/webhooks/Webhook.java | 21 +++++----- src/test/java/co/lettermint/WebhookTest.java | 40 +++++++++++++++++++ 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/main/java/co/lettermint/webhooks/Webhook.java b/src/main/java/co/lettermint/webhooks/Webhook.java index 8cab841..7c41cca 100644 --- a/src/main/java/co/lettermint/webhooks/Webhook.java +++ b/src/main/java/co/lettermint/webhooks/Webhook.java @@ -44,7 +44,8 @@ public static Map verify(String payload, String signature, Strin * @param payload The raw JSON payload string * @param signature The signature header value (format: "t={timestamp},v1={hash}") * @param secret The webhook signing secret - * @param tolerance Maximum allowed age in seconds (0 to disable timestamp check) + * @param tolerance Maximum allowed difference in seconds between the signature timestamp and the + * current time, in either direction (0 to disable timestamp check) * @return The parsed payload as a Map * @throws WebhookVerificationException if verification fails */ @@ -110,21 +111,21 @@ private static void verifyTimestamp(String timestampStr, int tolerance) { long now = System.currentTimeMillis() / 1000; - // Reject future timestamps and timestamps older than tolerance - if (timestamp > now) { + // Accept timestamps within the tolerance window in both directions so that + // small clock skew between sender and receiver does not break verification. + long age = now - timestamp; + if (age > tolerance) { throw new TimestampToleranceException( - String.format("Timestamp is in the future. Timestamp: %d, Current: %d", - timestamp, now), + String.format("Timestamp too old. Timestamp: %d, Current: %d, Age: %d seconds, Tolerance: %d seconds", + timestamp, now, age, tolerance), timestamp, tolerance ); } - - long age = now - timestamp; - if (age > tolerance) { + if (-age > tolerance) { throw new TimestampToleranceException( - String.format("Timestamp too old. Timestamp: %d, Current: %d, Age: %d seconds, Tolerance: %d seconds", - timestamp, now, age, tolerance), + String.format("Timestamp too far in the future. Timestamp: %d, Current: %d, Ahead: %d seconds, Tolerance: %d seconds", + timestamp, now, -age, tolerance), timestamp, tolerance ); diff --git a/src/test/java/co/lettermint/WebhookTest.java b/src/test/java/co/lettermint/WebhookTest.java index 098e7d7..ac0ac0a 100644 --- a/src/test/java/co/lettermint/WebhookTest.java +++ b/src/test/java/co/lettermint/WebhookTest.java @@ -66,6 +66,46 @@ void testTimestampOutsideTolerance() { assertEquals(300, ex.getTolerance()); } + @Test + void testFutureTimestampWithinToleranceIsValid() { + String payload = "{\"event\":\"test\"}"; + long futureTimestamp = (System.currentTimeMillis() / 1000) + 5; + String hash = computeHmac(futureTimestamp + "." + payload, TEST_SECRET); + String signature = "t=" + futureTimestamp + ",v1=" + hash; + + Map result = Webhook.verify(payload, signature, TEST_SECRET, 300); + + assertEquals("test", result.get("event")); + } + + @Test + void testFutureTimestampOutsideToleranceIsRejected() { + String payload = "{\"event\":\"test\"}"; + long futureTimestamp = (System.currentTimeMillis() / 1000) + 600; + String hash = computeHmac(futureTimestamp + "." + payload, TEST_SECRET); + String signature = "t=" + futureTimestamp + ",v1=" + hash; + + TimestampToleranceException ex = assertThrows(TimestampToleranceException.class, + () -> Webhook.verify(payload, signature, TEST_SECRET, 300)); + + assertEquals(futureTimestamp, ex.getTimestamp()); + assertEquals(300, ex.getTolerance()); + assertTrue(ex.getMessage().contains("future")); + } + + @Test + void testOldTimestampMessageMentionsAge() { + String payload = "{\"event\":\"test\"}"; + long oldTimestamp = (System.currentTimeMillis() / 1000) - 600; + String hash = computeHmac(oldTimestamp + "." + payload, TEST_SECRET); + String signature = "t=" + oldTimestamp + ",v1=" + hash; + + TimestampToleranceException ex = assertThrows(TimestampToleranceException.class, + () -> Webhook.verify(payload, signature, TEST_SECRET, 300)); + + assertTrue(ex.getMessage().contains("too old")); + } + @Test void testCustomTolerance() { String payload = "{\"event\":\"test\"}"; From 01c91b0086c9693d0ee13adfdfaaeb2fa790bd42 Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Sat, 3 Oct 2026 23:34:06 +0200 Subject: [PATCH 2/6] build: require Java 17 and add the generated API types src/main/java/co/lettermint/types is generated by the SDK generator (emit java, profile next, spec lettermint@80d8ab2a2d). ./gradlew generateTypes regenerates it with LETTERMINT_SDK_GENERATOR or ../sdk-generator; checkGeneratedTypes, part of check, verifies it or, without the generator, its headers. The build compiles with --release 17 on Gradle 9.6.1, and the version comes from -PreleaseVersion instead of a 2.0.0 placeholder. --- build.gradle | 166 +- gradle/wrapper/gradle-wrapper.jar | Bin 61624 -> 43764 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 37 +- gradlew.bat | 26 +- .../co/lettermint/BuildInfo.java | 10 - .../types/AnalyticsBreakdownRow.java | 113 ++ .../types/AnalyticsCatalogueDimension.java | 174 ++ .../AnalyticsCatalogueGroupDimension.java | 158 ++ .../lettermint/types/AnalyticsComparison.java | 82 + .../types/AnalyticsComparisonValues.java | 64 + .../lettermint/types/AnalyticsDimension.java | 178 ++ .../co/lettermint/types/AnalyticsFilter.java | 80 + .../types/AnalyticsFilterOperator.java | 98 + .../types/AnalyticsGroupDimension.java | 162 ++ .../lettermint/types/AnalyticsInterval.java | 86 + .../co/lettermint/types/AnalyticsMeta.java | 210 +++ .../types/AnalyticsMetaAlignment.java | 86 + .../AnalyticsMetaCollectionCompleteness.java | 78 + .../types/AnalyticsMetaComparison.java | 72 + .../types/AnalyticsMetaTimeBasis.java | 78 + .../co/lettermint/types/AnalyticsMetric.java | 346 ++++ .../types/AnalyticsMetricChange.java | 92 + .../types/AnalyticsMetricValues.java | 1116 +++++++++++ .../lettermint/types/AnalyticsPagination.java | 96 + .../co/lettermint/types/AnalyticsQuery.java | 189 ++ .../lettermint/types/AnalyticsRateBase.java | 76 + .../lettermint/types/AnalyticsRateBases.java | 114 ++ .../lettermint/types/AnalyticsResponse.java | 74 + .../co/lettermint/types/AnalyticsResults.java | 81 + .../co/lettermint/types/AnalyticsSection.java | 90 + .../co/lettermint/types/AnalyticsSort.java | 64 + .../types/AnalyticsSortDirection.java | 86 + .../co/lettermint/types/AnalyticsSummary.java | 90 + .../types/AnalyticsTimeSeriesPoint.java | 130 ++ .../java/co/lettermint/types/ApiError.java | 54 + .../co/lettermint/types/ApiErrorDetail.java | 72 + .../lettermint/types/AttachmentDelivery.java | 82 + .../co/lettermint/types/BlockedFileTypes.java | 71 + .../co/lettermint/types/BuiltInTeamRole.java | 86 + src/main/java/co/lettermint/types/Copies.java | 27 + .../java/co/lettermint/types/CursorPage.java | 47 + .../types/DeleteSuppressionResponse.java | 98 + .../DeleteSuppressionResponseStatus.java | 86 + .../co/lettermint/types/DeliveryMode.java | 82 + .../java/co/lettermint/types/DkimMode.java | 82 + .../java/co/lettermint/types/DmarcPolicy.java | 86 + .../co/lettermint/types/DnsRecordPurpose.java | 94 + .../co/lettermint/types/DnsRecordStatus.java | 94 + .../DnsRecordVerificationFailureResponse.java | 64 + .../types/DnsVerificationError.java | 64 + .../types/DnsVerificationFailedRecord.java | 74 + .../types/DnsVerificationFailureResponse.java | 113 ++ .../types/DnsVerificationResultData.java | 112 ++ ...ationResultDataDmarcSpfAlignmentIssue.java | 72 + .../types/DnsVerificationScope.java | 90 + .../types/DnsVerificationSuccessResponse.java | 70 + .../java/co/lettermint/types/DomainData.java | 129 ++ .../types/DomainDataProjectsItem.java | 62 + .../lettermint/types/DomainDnsRecordData.java | 152 ++ .../co/lettermint/types/DomainListData.java | 102 + .../types/DomainMutationResponse.java | 64 + .../co/lettermint/types/DomainStatus.java | 99 + .../co/lettermint/types/ErrorMessage.java | 54 + .../co/lettermint/types/GetDomainQuery.java | 64 + .../types/GetDomainQueryIncludeItem.java | 82 + .../co/lettermint/types/GetProjectQuery.java | 64 + .../types/GetProjectQueryIncludeItem.java | 110 ++ .../types/GetReportForwardingResponse.java | 52 + .../co/lettermint/types/GetRouteQuery.java | 75 + .../types/GetRouteQueryIncludeItem.java | 90 + .../co/lettermint/types/GetStatsQuery.java | 92 + .../co/lettermint/types/GetTeamQuery.java | 64 + .../types/GetTeamQueryIncludeItem.java | 82 + .../types/InboundDomainVerification.java | 91 + .../InboundDomainVerificationResponse.java | 54 + .../co/lettermint/types/InitialRoutes.java | 86 + .../co/lettermint/types/ListDomainsQuery.java | 125 ++ .../types/ListDomainsQuerySortItem.java | 98 + .../types/ListMessageEventsQuery.java | 103 + .../types/ListMessageEventsQuerySortItem.java | 90 + .../lettermint/types/ListMessagesQuery.java | 279 +++ .../types/ListMessagesQueryFilter.java | 58 + .../ListMessagesQueryFilterTagsItem.java | 62 + .../types/ListMessagesQuerySortItem.java | 130 ++ .../lettermint/types/ListProjectsQuery.java | 103 + .../types/ListProjectsQuerySortItem.java | 90 + .../co/lettermint/types/ListRoutesQuery.java | 125 ++ .../types/ListRoutesQuerySortItem.java | 98 + .../types/ListSuppressionsQuery.java | 169 ++ .../types/ListSuppressionsQuerySortItem.java | 98 + .../types/ListTeamMembersQuery.java | 76 + .../types/ListWebhookDeliveriesQuery.java | 119 ++ .../ListWebhookDeliveriesQuerySortItem.java | 90 + .../lettermint/types/ListWebhooksQuery.java | 158 ++ .../types/ListWebhooksQuerySortItem.java | 98 + .../types/MessageAttachmentData.java | 88 + .../types/MessageAttachmentInput.java | 84 + .../java/co/lettermint/types/MessageData.java | 282 +++ .../co/lettermint/types/MessageEventData.java | 110 ++ .../co/lettermint/types/MessageEventType.java | 170 ++ .../co/lettermint/types/MessageListData.java | 238 +++ .../types/MessageRecipientData.java | 72 + .../co/lettermint/types/MessageResponse.java | 54 + .../co/lettermint/types/MessageStatsData.java | 106 ++ .../co/lettermint/types/MessageStatus.java | 142 ++ .../java/co/lettermint/types/MessageTag.java | 62 + .../co/lettermint/types/MessageTagInput.java | 64 + .../java/co/lettermint/types/MessageType.java | 82 + .../java/co/lettermint/types/Operations.java | 1670 +++++++++++++++++ .../co/lettermint/types/OptionalNullable.java | 122 ++ .../types/PendingSendMailResponse.java | 84 + src/main/java/co/lettermint/types/Plan.java | 90 + .../types/ProcessInboundMessageConflict.java | 52 + .../ProcessInboundMessageConflictError.java | 62 + ...rocessInboundMessageConflictErrorCode.java | 86 + .../types/ProcessInboundMessageResponse.java | 54 + .../types/ProcessInboundMessageResult.java | 80 + .../lettermint/types/ProjectAccessScope.java | 82 + .../lettermint/types/ProjectCreatedData.java | 80 + .../java/co/lettermint/types/ProjectData.java | 221 +++ .../co/lettermint/types/ProjectListData.java | 144 ++ .../types/ProjectMutationResponse.java | 64 + .../co/lettermint/types/QueryParameters.java | 21 + .../co/lettermint/types/RbacConflictCode.java | 94 + .../types/RbacConflictException.java | 54 + .../types/RbacConflictExceptionError.java | 62 + .../co/lettermint/types/RbacPermission.java | 238 +++ .../java/co/lettermint/types/RecordType.java | 86 + .../types/ReportForwardingRequest.java | 52 + .../types/ReportForwardingResource.java | 72 + .../types/RescheduleMessageRequest.java | 52 + .../ResendReportForwardingCodeResponse.java | 52 + .../types/RotateProjectTokenResponse.java | 82 + .../java/co/lettermint/types/RouteData.java | 266 +++ .../lettermint/types/RouteDataSettings.java | 134 ++ .../co/lettermint/types/RouteListData.java | 144 ++ .../types/RouteMutationResponse.java | 64 + .../lettermint/types/RouteStatisticData.java | 260 +++ .../java/co/lettermint/types/RouteType.java | 86 + .../co/lettermint/types/SandboxResult.java | 118 ++ .../co/lettermint/types/ScheduledMessage.java | 74 + .../types/ScheduledSendMailResponse.java | 94 + .../co/lettermint/types/SendMailRequest.java | 226 +++ .../types/SendMailRequestSettings.java | 74 + .../co/lettermint/types/SendMailResponse.java | 92 + .../java/co/lettermint/types/SpamSymbol.java | 94 + .../co/lettermint/types/StatsDailyData.java | 274 +++ .../java/co/lettermint/types/StatsData.java | 88 + .../co/lettermint/types/StatsInboundData.java | 58 + .../co/lettermint/types/StatsTotalsData.java | 264 +++ .../co/lettermint/types/StatsTypeData.java | 90 + .../co/lettermint/types/StoreDomainData.java | 52 + .../co/lettermint/types/StoreProjectData.java | 102 + .../co/lettermint/types/StoreRouteData.java | 128 ++ .../types/StoreSuppressionData.java | 118 ++ .../co/lettermint/types/StoreWebhookData.java | 160 ++ .../types/SuppressedRecipientData.java | 142 ++ .../types/SuppressionAppliesTo.java | 86 + .../types/SuppressionCreateReason.java | 94 + .../types/SuppressionCreateScope.java | 90 + .../types/SuppressionDeletedResponse.java | 90 + .../lettermint/types/SuppressionReason.java | 98 + .../types/SuppressionReviewResponse.java | 100 + .../SuppressionReviewResponseStatus.java | 82 + .../co/lettermint/types/SuppressionScope.java | 98 + .../types/SuppressionSourceMessageData.java | 82 + .../types/SuppressionStoreResponse.java | 64 + .../types/SuppressionStoreResult.java | 71 + .../co/lettermint/types/SuppressionType.java | 86 + .../co/lettermint/types/TeamAddonData.java | 62 + .../java/co/lettermint/types/TeamData.java | 222 +++ .../co/lettermint/types/TeamMemberData.java | 102 + .../lettermint/types/TeamMemberDataRole.java | 62 + .../types/TeamMemberProjectAccessData.java | 68 + ...amMemberProjectAccessDataProjectsItem.java | 62 + .../types/TeamMutationResponse.java | 64 + .../co/lettermint/types/TeamRoleData.java | 98 + .../types/TeamRoleListResponse.java | 60 + .../java/co/lettermint/types/TeamType.java | 82 + .../lettermint/types/TeamUsageDetailData.java | 68 + .../lettermint/types/TeamUsagePeriodData.java | 88 + .../lettermint/types/TestWebhookResponse.java | 64 + .../java/co/lettermint/types/TlsPolicy.java | 82 + .../types/UpdateDomainProjectsData.java | 58 + .../lettermint/types/UpdateProjectData.java | 92 + .../types/UpdateReportForwardingResponse.java | 52 + .../co/lettermint/types/UpdateRouteData.java | 108 ++ .../types/UpdateRouteInboundSettingsData.java | 78 + .../types/UpdateRouteSettingsData.java | 122 ++ .../co/lettermint/types/UpdateTeamData.java | 52 + .../types/UpdateTeamMemberAssignmentData.java | 62 + ...TeamMemberAssignmentDataProjectAccess.java | 68 + .../lettermint/types/UpdateWebhookData.java | 160 ++ .../co/lettermint/types/ValidationError.java | 69 + .../types/VerifyReportForwardingRequest.java | 52 + .../types/VerifyReportForwardingResponse.java | 52 + .../types/WebhookBasicAuthData.java | 69 + .../java/co/lettermint/types/WebhookData.java | 212 +++ .../lettermint/types/WebhookDeliveryData.java | 237 +++ .../types/WebhookDeliveryListData.java | 190 ++ .../types/WebhookDeliveryModeFilter.java | 86 + .../types/WebhookDeliveryStatus.java | 98 + .../co/lettermint/types/WebhookEvent.java | 158 ++ .../co/lettermint/types/WebhookListData.java | 202 ++ .../types/WebhookMutationResponse.java | 64 + .../co/lettermint/types/WebhookScope.java | 86 + .../lettermint/types/WebhookSecretData.java | 243 +++ .../types/WebhookSecretResponse.java | 64 + 209 files changed, 23567 insertions(+), 66 deletions(-) delete mode 100644 src/main/java-templates/co/lettermint/BuildInfo.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsComparison.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsComparisonValues.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsDimension.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsFilter.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsFilterOperator.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsGroupDimension.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsInterval.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMeta.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetaComparison.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetric.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetricChange.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsMetricValues.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsPagination.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsQuery.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsRateBase.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsRateBases.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsResponse.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsResults.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsSection.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsSort.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsSortDirection.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsSummary.java create mode 100644 src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java create mode 100644 src/main/java/co/lettermint/types/ApiError.java create mode 100644 src/main/java/co/lettermint/types/ApiErrorDetail.java create mode 100644 src/main/java/co/lettermint/types/AttachmentDelivery.java create mode 100644 src/main/java/co/lettermint/types/BlockedFileTypes.java create mode 100644 src/main/java/co/lettermint/types/BuiltInTeamRole.java create mode 100644 src/main/java/co/lettermint/types/Copies.java create mode 100644 src/main/java/co/lettermint/types/CursorPage.java create mode 100644 src/main/java/co/lettermint/types/DeleteSuppressionResponse.java create mode 100644 src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java create mode 100644 src/main/java/co/lettermint/types/DeliveryMode.java create mode 100644 src/main/java/co/lettermint/types/DkimMode.java create mode 100644 src/main/java/co/lettermint/types/DmarcPolicy.java create mode 100644 src/main/java/co/lettermint/types/DnsRecordPurpose.java create mode 100644 src/main/java/co/lettermint/types/DnsRecordStatus.java create mode 100644 src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationError.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationResultData.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationScope.java create mode 100644 src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java create mode 100644 src/main/java/co/lettermint/types/DomainData.java create mode 100644 src/main/java/co/lettermint/types/DomainDataProjectsItem.java create mode 100644 src/main/java/co/lettermint/types/DomainDnsRecordData.java create mode 100644 src/main/java/co/lettermint/types/DomainListData.java create mode 100644 src/main/java/co/lettermint/types/DomainMutationResponse.java create mode 100644 src/main/java/co/lettermint/types/DomainStatus.java create mode 100644 src/main/java/co/lettermint/types/ErrorMessage.java create mode 100644 src/main/java/co/lettermint/types/GetDomainQuery.java create mode 100644 src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java create mode 100644 src/main/java/co/lettermint/types/GetProjectQuery.java create mode 100644 src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java create mode 100644 src/main/java/co/lettermint/types/GetReportForwardingResponse.java create mode 100644 src/main/java/co/lettermint/types/GetRouteQuery.java create mode 100644 src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java create mode 100644 src/main/java/co/lettermint/types/GetStatsQuery.java create mode 100644 src/main/java/co/lettermint/types/GetTeamQuery.java create mode 100644 src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java create mode 100644 src/main/java/co/lettermint/types/InboundDomainVerification.java create mode 100644 src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java create mode 100644 src/main/java/co/lettermint/types/InitialRoutes.java create mode 100644 src/main/java/co/lettermint/types/ListDomainsQuery.java create mode 100644 src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListMessageEventsQuery.java create mode 100644 src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListMessagesQuery.java create mode 100644 src/main/java/co/lettermint/types/ListMessagesQueryFilter.java create mode 100644 src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java create mode 100644 src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListProjectsQuery.java create mode 100644 src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListRoutesQuery.java create mode 100644 src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListSuppressionsQuery.java create mode 100644 src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListTeamMembersQuery.java create mode 100644 src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java create mode 100644 src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/ListWebhooksQuery.java create mode 100644 src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java create mode 100644 src/main/java/co/lettermint/types/MessageAttachmentData.java create mode 100644 src/main/java/co/lettermint/types/MessageAttachmentInput.java create mode 100644 src/main/java/co/lettermint/types/MessageData.java create mode 100644 src/main/java/co/lettermint/types/MessageEventData.java create mode 100644 src/main/java/co/lettermint/types/MessageEventType.java create mode 100644 src/main/java/co/lettermint/types/MessageListData.java create mode 100644 src/main/java/co/lettermint/types/MessageRecipientData.java create mode 100644 src/main/java/co/lettermint/types/MessageResponse.java create mode 100644 src/main/java/co/lettermint/types/MessageStatsData.java create mode 100644 src/main/java/co/lettermint/types/MessageStatus.java create mode 100644 src/main/java/co/lettermint/types/MessageTag.java create mode 100644 src/main/java/co/lettermint/types/MessageTagInput.java create mode 100644 src/main/java/co/lettermint/types/MessageType.java create mode 100644 src/main/java/co/lettermint/types/Operations.java create mode 100644 src/main/java/co/lettermint/types/OptionalNullable.java create mode 100644 src/main/java/co/lettermint/types/PendingSendMailResponse.java create mode 100644 src/main/java/co/lettermint/types/Plan.java create mode 100644 src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java create mode 100644 src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java create mode 100644 src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java create mode 100644 src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java create mode 100644 src/main/java/co/lettermint/types/ProcessInboundMessageResult.java create mode 100644 src/main/java/co/lettermint/types/ProjectAccessScope.java create mode 100644 src/main/java/co/lettermint/types/ProjectCreatedData.java create mode 100644 src/main/java/co/lettermint/types/ProjectData.java create mode 100644 src/main/java/co/lettermint/types/ProjectListData.java create mode 100644 src/main/java/co/lettermint/types/ProjectMutationResponse.java create mode 100644 src/main/java/co/lettermint/types/QueryParameters.java create mode 100644 src/main/java/co/lettermint/types/RbacConflictCode.java create mode 100644 src/main/java/co/lettermint/types/RbacConflictException.java create mode 100644 src/main/java/co/lettermint/types/RbacConflictExceptionError.java create mode 100644 src/main/java/co/lettermint/types/RbacPermission.java create mode 100644 src/main/java/co/lettermint/types/RecordType.java create mode 100644 src/main/java/co/lettermint/types/ReportForwardingRequest.java create mode 100644 src/main/java/co/lettermint/types/ReportForwardingResource.java create mode 100644 src/main/java/co/lettermint/types/RescheduleMessageRequest.java create mode 100644 src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java create mode 100644 src/main/java/co/lettermint/types/RotateProjectTokenResponse.java create mode 100644 src/main/java/co/lettermint/types/RouteData.java create mode 100644 src/main/java/co/lettermint/types/RouteDataSettings.java create mode 100644 src/main/java/co/lettermint/types/RouteListData.java create mode 100644 src/main/java/co/lettermint/types/RouteMutationResponse.java create mode 100644 src/main/java/co/lettermint/types/RouteStatisticData.java create mode 100644 src/main/java/co/lettermint/types/RouteType.java create mode 100644 src/main/java/co/lettermint/types/SandboxResult.java create mode 100644 src/main/java/co/lettermint/types/ScheduledMessage.java create mode 100644 src/main/java/co/lettermint/types/ScheduledSendMailResponse.java create mode 100644 src/main/java/co/lettermint/types/SendMailRequest.java create mode 100644 src/main/java/co/lettermint/types/SendMailRequestSettings.java create mode 100644 src/main/java/co/lettermint/types/SendMailResponse.java create mode 100644 src/main/java/co/lettermint/types/SpamSymbol.java create mode 100644 src/main/java/co/lettermint/types/StatsDailyData.java create mode 100644 src/main/java/co/lettermint/types/StatsData.java create mode 100644 src/main/java/co/lettermint/types/StatsInboundData.java create mode 100644 src/main/java/co/lettermint/types/StatsTotalsData.java create mode 100644 src/main/java/co/lettermint/types/StatsTypeData.java create mode 100644 src/main/java/co/lettermint/types/StoreDomainData.java create mode 100644 src/main/java/co/lettermint/types/StoreProjectData.java create mode 100644 src/main/java/co/lettermint/types/StoreRouteData.java create mode 100644 src/main/java/co/lettermint/types/StoreSuppressionData.java create mode 100644 src/main/java/co/lettermint/types/StoreWebhookData.java create mode 100644 src/main/java/co/lettermint/types/SuppressedRecipientData.java create mode 100644 src/main/java/co/lettermint/types/SuppressionAppliesTo.java create mode 100644 src/main/java/co/lettermint/types/SuppressionCreateReason.java create mode 100644 src/main/java/co/lettermint/types/SuppressionCreateScope.java create mode 100644 src/main/java/co/lettermint/types/SuppressionDeletedResponse.java create mode 100644 src/main/java/co/lettermint/types/SuppressionReason.java create mode 100644 src/main/java/co/lettermint/types/SuppressionReviewResponse.java create mode 100644 src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java create mode 100644 src/main/java/co/lettermint/types/SuppressionScope.java create mode 100644 src/main/java/co/lettermint/types/SuppressionSourceMessageData.java create mode 100644 src/main/java/co/lettermint/types/SuppressionStoreResponse.java create mode 100644 src/main/java/co/lettermint/types/SuppressionStoreResult.java create mode 100644 src/main/java/co/lettermint/types/SuppressionType.java create mode 100644 src/main/java/co/lettermint/types/TeamAddonData.java create mode 100644 src/main/java/co/lettermint/types/TeamData.java create mode 100644 src/main/java/co/lettermint/types/TeamMemberData.java create mode 100644 src/main/java/co/lettermint/types/TeamMemberDataRole.java create mode 100644 src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java create mode 100644 src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java create mode 100644 src/main/java/co/lettermint/types/TeamMutationResponse.java create mode 100644 src/main/java/co/lettermint/types/TeamRoleData.java create mode 100644 src/main/java/co/lettermint/types/TeamRoleListResponse.java create mode 100644 src/main/java/co/lettermint/types/TeamType.java create mode 100644 src/main/java/co/lettermint/types/TeamUsageDetailData.java create mode 100644 src/main/java/co/lettermint/types/TeamUsagePeriodData.java create mode 100644 src/main/java/co/lettermint/types/TestWebhookResponse.java create mode 100644 src/main/java/co/lettermint/types/TlsPolicy.java create mode 100644 src/main/java/co/lettermint/types/UpdateDomainProjectsData.java create mode 100644 src/main/java/co/lettermint/types/UpdateProjectData.java create mode 100644 src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java create mode 100644 src/main/java/co/lettermint/types/UpdateRouteData.java create mode 100644 src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java create mode 100644 src/main/java/co/lettermint/types/UpdateRouteSettingsData.java create mode 100644 src/main/java/co/lettermint/types/UpdateTeamData.java create mode 100644 src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java create mode 100644 src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java create mode 100644 src/main/java/co/lettermint/types/UpdateWebhookData.java create mode 100644 src/main/java/co/lettermint/types/ValidationError.java create mode 100644 src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java create mode 100644 src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java create mode 100644 src/main/java/co/lettermint/types/WebhookBasicAuthData.java create mode 100644 src/main/java/co/lettermint/types/WebhookData.java create mode 100644 src/main/java/co/lettermint/types/WebhookDeliveryData.java create mode 100644 src/main/java/co/lettermint/types/WebhookDeliveryListData.java create mode 100644 src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java create mode 100644 src/main/java/co/lettermint/types/WebhookDeliveryStatus.java create mode 100644 src/main/java/co/lettermint/types/WebhookEvent.java create mode 100644 src/main/java/co/lettermint/types/WebhookListData.java create mode 100644 src/main/java/co/lettermint/types/WebhookMutationResponse.java create mode 100644 src/main/java/co/lettermint/types/WebhookScope.java create mode 100644 src/main/java/co/lettermint/types/WebhookSecretData.java create mode 100644 src/main/java/co/lettermint/types/WebhookSecretResponse.java diff --git a/build.gradle b/build.gradle index e942d6e..d0b1add 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,5 @@ +import javax.inject.Inject + plugins { id 'java-library' id 'maven-publish' @@ -5,11 +7,10 @@ plugins { } group = 'co.lettermint' -version = '2.0.0' +// The release workflow passes the version from the git tag: -PreleaseVersion=3.0.0. +version = providers.gradleProperty('releaseVersion').getOrElse('3.0.0-SNAPSHOT') java { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 withSourcesJar() withJavadocJar() } @@ -19,59 +20,158 @@ repositories { } dependencies { - // HTTP Client + // Generated types use Jackson annotations and TypeReference in their public API. + api 'com.fasterxml.jackson.core:jackson-databind:2.22.3' implementation 'com.squareup.okhttp3:okhttp:4.12.0' - // JSON Processing - implementation 'com.fasterxml.jackson.core:jackson-databind:2.22.3' - - // Testing testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +tasks.withType(JavaCompile).configureEach { + options.release = 17 + options.encoding = 'UTF-8' } -test { +tasks.named('test', Test) { useJUnitPlatform() + testLogging { + events 'failed' + exceptionFormat 'full' + } +} + +tasks.named('javadoc', Javadoc) { + options.encoding = 'UTF-8' + options.addStringOption('Xdoclint:all,-missing', '-quiet') } -// Generate BuildInfo.java with version from Gradle -def generatedSrcDir = layout.buildDirectory.dir('generated/sources/buildinfo/java/main') +// BuildInfo.VERSION (User-Agent) comes from the project version. +def buildInfoDir = layout.buildDirectory.dir('generated/sources/buildinfo/java/main') -tasks.register('generateBuildInfo') { - def outputDir = generatedSrcDir +def generateBuildInfo = tasks.register('generateBuildInfo') { + def outputDir = buildInfoDir + def sdkVersion = project.version.toString() + inputs.property('version', sdkVersion) outputs.dir(outputDir) doLast { - def dir = outputDir.get().asFile - dir.mkdirs() - def packageDir = new File(dir, 'co/lettermint') - packageDir.mkdirs() - new File(packageDir, 'BuildInfo.java').text = """package co.lettermint; - -/** - * Auto-generated build information. - */ + def file = outputDir.get().file('co/lettermint/BuildInfo.java').asFile + file.parentFile.mkdirs() + file.text = """package co.lettermint; + +/** Build information, generated by Gradle. */ public final class BuildInfo { - public static final String VERSION = "${project.version}"; + /** The SDK version. */ + public static final String VERSION = "${sdkVersion}"; - private BuildInfo() {} + private BuildInfo() { + } } """ } } -sourceSets.main.java.srcDir(generatedSrcDir) -compileJava.dependsOn(generateBuildInfo) -sourcesJar.dependsOn(generateBuildInfo) +sourceSets.main.java.srcDir(generateBuildInfo) jar { manifest { attributes( 'Implementation-Title': 'Lettermint Java SDK', - 'Implementation-Version': version + 'Implementation-Version': project.version, + 'Automatic-Module-Name': 'co.lettermint' ) } } +// src/main/java/co/lettermint/types is generated by the private lettermint/sdk-generator. +// Set LETTERMINT_SDK_GENERATOR to its checkout (default: ../sdk-generator). +// ./gradlew generateTypes regenerates the package +// ./gradlew checkGeneratedTypes verifies it (part of `check`). Without the generator, +// as in CI, it only verifies the generated headers. +abstract class GeneratedTypesTask extends DefaultTask { + @Inject + abstract ExecOperations getExecOperations() + + @Internal + abstract DirectoryProperty getTypesDir() + + @Internal + abstract Property getGenerator() + + @Internal + abstract Property getCheckOnly() + + @TaskAction + void run() { + File generator = new File(getGenerator().get()) + File out = getTypesDir().get().asFile + boolean available = new File(generator, 'lettermint_sdkgen').isDirectory() && new File(generator, 'spec.next.lock.json').isFile() + if (available) { + List command = ['python3', '-m', 'lettermint_sdkgen', 'emit', 'java', '--profile', 'next', '--lock', 'spec.next.lock.json', '--out', out.absolutePath] + if (getCheckOnly().get()) { + command << '--check' + } + getExecOperations().exec { + workingDir generator + commandLine command + } + return + } + if (!getCheckOnly().get()) { + throw new GradleException("The SDK generator was not found at ${generator}. Set LETTERMINT_SDK_GENERATOR to its checkout.") + } + String first = null + File[] files = out.listFiles({ File f -> f.name.endsWith('.java') } as FileFilter) + if (files == null || files.length == 0) { + throw new GradleException("${out} has no generated sources.") + } + for (File file : files.sort { it.name }) { + List lines = file.readLines('UTF-8') + String head = lines.take(5).join('\n') + boolean valid = lines.size() > 5 && + lines[0] == '// Generated by lettermint/sdk-generator — do not edit.' && + lines[1] ==~ /\/\/ Spec: lettermint\/lettermint@[0-9a-f]{40}( \(.+\))?/ && + lines[2] ==~ /\/\/ sending-openapi\.json SHA-256: [0-9a-f]{64}/ && + lines[3] ==~ /\/\/ team-openapi\.json SHA-256: [0-9a-f]{64}/ && + lines[4] == '// Naming profile: next' + if (!valid) { + throw new GradleException("${file} is missing the generator header. Regenerate it; do not edit it by hand.") + } + if (first == null) { + first = head + } else if (first != head) { + throw new GradleException("${file.name} comes from a different spec than the other generated files. Regenerate the package.") + } + } + logger.lifecycle("SDK generator not found at ${generator}; checked the headers of ${files.length} generated files only.") + logger.lifecycle(first.split('\n')[1]) + } +} + +def generatorPath = providers.environmentVariable('LETTERMINT_SDK_GENERATOR') + .orElse(layout.projectDirectory.dir('../sdk-generator').asFile.absolutePath) + +tasks.register('generateTypes', GeneratedTypesTask) { + group = 'build' + description = 'Regenerates src/main/java/co/lettermint/types with the SDK generator.' + typesDir = layout.projectDirectory.dir('src/main/java/co/lettermint/types') + generator = generatorPath + checkOnly = false +} + +def checkGeneratedTypes = tasks.register('checkGeneratedTypes', GeneratedTypesTask) { + group = 'verification' + description = 'Verifies src/main/java/co/lettermint/types against the SDK generator, or its headers without it.' + typesDir = layout.projectDirectory.dir('src/main/java/co/lettermint/types') + generator = generatorPath + checkOnly = true +} + +tasks.named('check') { + dependsOn checkGeneratedTypes +} + publishing { publications { maven(MavenPublication) { @@ -119,6 +219,16 @@ publishing { } } +// Never publish the -SNAPSHOT placeholder: releases must pass -PreleaseVersion. +def publishedVersion = project.version.toString() +tasks.withType(PublishToMavenRepository).configureEach { + doFirst { + if (publishedVersion.endsWith('-SNAPSHOT')) { + throw new GradleException("Refusing to publish ${publishedVersion}; pass -PreleaseVersion=.") + } + } +} + signing { // Uses ORG_GRADLE_PROJECT_signingKey, signingKeyId, signingPassword from env def signingKey = findProperty('signingKey') diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index afba109285af78dbd2a1d187e33ac4f87c76e392..1b33c55baabb587c669f562ae36f953de2481846 100644 GIT binary patch literal 43764 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�Zy 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3c44eb1..a351597 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.6.1-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..23d15a9 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,10 +85,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -133,10 +133,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,16 +200,20 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..db3a6ac 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,22 +59,22 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/src/main/java-templates/co/lettermint/BuildInfo.java b/src/main/java-templates/co/lettermint/BuildInfo.java deleted file mode 100644 index 5bd659f..0000000 --- a/src/main/java-templates/co/lettermint/BuildInfo.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint; - -/** - * Auto-generated build information. - */ -public final class BuildInfo { - public static final String VERSION = "${project.version}"; - - private BuildInfo() {} -} diff --git a/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java b/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java new file mode 100644 index 0000000..24893c3 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java @@ -0,0 +1,113 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +/** + * Metric values for one group of dimension values. + * + * @param metrics Always present. + * @param rateBases Always present. + * @param previous Optional: null when absent. + * @param change Optional: null when absent. + * @param dimensions Always present. + * @param trend Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsBreakdownRow( + @JsonProperty("metrics") AnalyticsMetricValues metrics, + @JsonProperty("rate_bases") AnalyticsRateBases rateBases, + @JsonProperty("previous") AnalyticsComparisonValues previous, + @JsonProperty("change") Map change, + @JsonProperty("dimensions") Map dimensions, + @JsonProperty("trend") List trend +) { + /** Copies lists and maps into unmodifiable collections. */ + public AnalyticsBreakdownRow { + change = Copies.map(change); + dimensions = Copies.map(dimensions); + trend = Copies.list(trend); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsBreakdownRow. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.metrics = metrics; + builder.rateBases = rateBases; + builder.previous = previous; + builder.change = change; + builder.dimensions = dimensions; + builder.trend = trend; + return builder; + } + + /** Builds a {@link AnalyticsBreakdownRow}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsMetricValues metrics; + private AnalyticsRateBases rateBases; + private AnalyticsComparisonValues previous; + private Map change; + private Map dimensions; + private List trend; + + private Builder() { + } + + /** Sets {@code metrics}. */ + public Builder metrics(AnalyticsMetricValues metrics) { + this.metrics = metrics; + return this; + } + + /** Sets {@code rate_bases}. */ + public Builder rateBases(AnalyticsRateBases rateBases) { + this.rateBases = rateBases; + return this; + } + + /** Sets {@code previous}. */ + public Builder previous(AnalyticsComparisonValues previous) { + this.previous = previous; + return this; + } + + /** Sets {@code change}. */ + public Builder change(Map change) { + this.change = change; + return this; + } + + /** Sets {@code dimensions}. */ + public Builder dimensions(Map dimensions) { + this.dimensions = dimensions; + return this; + } + + /** Sets {@code trend}. */ + public Builder trend(List trend) { + this.trend = trend; + return this; + } + + /** Returns the {@link AnalyticsBreakdownRow}. */ + public AnalyticsBreakdownRow build() { + return new AnalyticsBreakdownRow(metrics, rateBases, previous, change, dimensions, trend); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java b/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java new file mode 100644 index 0000000..7c5285b --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java @@ -0,0 +1,174 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class AnalyticsCatalogueDimension { + /** {@code "project_id"} */ + public static final AnalyticsCatalogueDimension PROJECT_ID = new AnalyticsCatalogueDimension("project_id"); + + /** {@code "route_id"} */ + public static final AnalyticsCatalogueDimension ROUTE_ID = new AnalyticsCatalogueDimension("route_id"); + + /** {@code "message_type"} */ + public static final AnalyticsCatalogueDimension MESSAGE_TYPE = new AnalyticsCatalogueDimension("message_type"); + + /** {@code "sending_domain"} */ + public static final AnalyticsCatalogueDimension SENDING_DOMAIN = new AnalyticsCatalogueDimension("sending_domain"); + + /** {@code "recipient_domain"} */ + public static final AnalyticsCatalogueDimension RECIPIENT_DOMAIN = new AnalyticsCatalogueDimension("recipient_domain"); + + /** {@code "provider_family"} */ + public static final AnalyticsCatalogueDimension PROVIDER_FAMILY = new AnalyticsCatalogueDimension("provider_family"); + + /** {@code "provider_subtype"} */ + public static final AnalyticsCatalogueDimension PROVIDER_SUBTYPE = new AnalyticsCatalogueDimension("provider_subtype"); + + /** {@code "from_address"} */ + public static final AnalyticsCatalogueDimension FROM_ADDRESS = new AnalyticsCatalogueDimension("from_address"); + + /** {@code "subject"} */ + public static final AnalyticsCatalogueDimension SUBJECT = new AnalyticsCatalogueDimension("subject"); + + /** {@code "dedicated_ip"} */ + public static final AnalyticsCatalogueDimension DEDICATED_IP = new AnalyticsCatalogueDimension("dedicated_ip"); + + /** {@code "dedicated_pool_id"} */ + public static final AnalyticsCatalogueDimension DEDICATED_POOL_ID = new AnalyticsCatalogueDimension("dedicated_pool_id"); + + /** {@code "infrastructure_state"} */ + public static final AnalyticsCatalogueDimension INFRASTRUCTURE_STATE = new AnalyticsCatalogueDimension("infrastructure_state"); + + /** {@code "smtp_code"} */ + public static final AnalyticsCatalogueDimension SMTP_CODE = new AnalyticsCatalogueDimension("smtp_code"); + + /** {@code "enhanced_status_code"} */ + public static final AnalyticsCatalogueDimension ENHANCED_STATUS_CODE = new AnalyticsCatalogueDimension("enhanced_status_code"); + + /** {@code "enhanced_status_category"} */ + public static final AnalyticsCatalogueDimension ENHANCED_STATUS_CATEGORY = new AnalyticsCatalogueDimension("enhanced_status_category"); + + /** {@code "bounce_classification"} */ + public static final AnalyticsCatalogueDimension BOUNCE_CLASSIFICATION = new AnalyticsCatalogueDimension("bounce_classification"); + + /** {@code "failure_reason"} */ + public static final AnalyticsCatalogueDimension FAILURE_REASON = new AnalyticsCatalogueDimension("failure_reason"); + + /** {@code "smtp_response_group"} */ + public static final AnalyticsCatalogueDimension SMTP_RESPONSE_GROUP = new AnalyticsCatalogueDimension("smtp_response_group"); + + /** {@code "engagement_state"} */ + public static final AnalyticsCatalogueDimension ENGAGEMENT_STATE = new AnalyticsCatalogueDimension("engagement_state"); + + /** {@code "request_actor"} */ + public static final AnalyticsCatalogueDimension REQUEST_ACTOR = new AnalyticsCatalogueDimension("request_actor"); + + /** {@code "proxy_type"} */ + public static final AnalyticsCatalogueDimension PROXY_TYPE = new AnalyticsCatalogueDimension("proxy_type"); + + /** {@code "is_human"} */ + public static final AnalyticsCatalogueDimension IS_HUMAN = new AnalyticsCatalogueDimension("is_human"); + + /** {@code "is_privacy"} */ + public static final AnalyticsCatalogueDimension IS_PRIVACY = new AnalyticsCatalogueDimension("is_privacy"); + + /** {@code "is_bot"} */ + public static final AnalyticsCatalogueDimension IS_BOT = new AnalyticsCatalogueDimension("is_bot"); + + /** {@code "is_scanner"} */ + public static final AnalyticsCatalogueDimension IS_SCANNER = new AnalyticsCatalogueDimension("is_scanner"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PROJECT_ID.value, PROJECT_ID); + known.put(ROUTE_ID.value, ROUTE_ID); + known.put(MESSAGE_TYPE.value, MESSAGE_TYPE); + known.put(SENDING_DOMAIN.value, SENDING_DOMAIN); + known.put(RECIPIENT_DOMAIN.value, RECIPIENT_DOMAIN); + known.put(PROVIDER_FAMILY.value, PROVIDER_FAMILY); + known.put(PROVIDER_SUBTYPE.value, PROVIDER_SUBTYPE); + known.put(FROM_ADDRESS.value, FROM_ADDRESS); + known.put(SUBJECT.value, SUBJECT); + known.put(DEDICATED_IP.value, DEDICATED_IP); + known.put(DEDICATED_POOL_ID.value, DEDICATED_POOL_ID); + known.put(INFRASTRUCTURE_STATE.value, INFRASTRUCTURE_STATE); + known.put(SMTP_CODE.value, SMTP_CODE); + known.put(ENHANCED_STATUS_CODE.value, ENHANCED_STATUS_CODE); + known.put(ENHANCED_STATUS_CATEGORY.value, ENHANCED_STATUS_CATEGORY); + known.put(BOUNCE_CLASSIFICATION.value, BOUNCE_CLASSIFICATION); + known.put(FAILURE_REASON.value, FAILURE_REASON); + known.put(SMTP_RESPONSE_GROUP.value, SMTP_RESPONSE_GROUP); + known.put(ENGAGEMENT_STATE.value, ENGAGEMENT_STATE); + known.put(REQUEST_ACTOR.value, REQUEST_ACTOR); + known.put(PROXY_TYPE.value, PROXY_TYPE); + known.put(IS_HUMAN.value, IS_HUMAN); + known.put(IS_PRIVACY.value, IS_PRIVACY); + known.put(IS_BOT.value, IS_BOT); + known.put(IS_SCANNER.value, IS_SCANNER); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsCatalogueDimension(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsCatalogueDimension of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsCatalogueDimension known = KNOWN.get(value); + return known != null ? known : new AnalyticsCatalogueDimension(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsCatalogueDimension that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java b/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java new file mode 100644 index 0000000..c690978 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java @@ -0,0 +1,158 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class AnalyticsCatalogueGroupDimension { + /** {@code "project_id"} */ + public static final AnalyticsCatalogueGroupDimension PROJECT_ID = new AnalyticsCatalogueGroupDimension("project_id"); + + /** {@code "route_id"} */ + public static final AnalyticsCatalogueGroupDimension ROUTE_ID = new AnalyticsCatalogueGroupDimension("route_id"); + + /** {@code "message_type"} */ + public static final AnalyticsCatalogueGroupDimension MESSAGE_TYPE = new AnalyticsCatalogueGroupDimension("message_type"); + + /** {@code "sending_domain"} */ + public static final AnalyticsCatalogueGroupDimension SENDING_DOMAIN = new AnalyticsCatalogueGroupDimension("sending_domain"); + + /** {@code "recipient_domain"} */ + public static final AnalyticsCatalogueGroupDimension RECIPIENT_DOMAIN = new AnalyticsCatalogueGroupDimension("recipient_domain"); + + /** {@code "provider_family"} */ + public static final AnalyticsCatalogueGroupDimension PROVIDER_FAMILY = new AnalyticsCatalogueGroupDimension("provider_family"); + + /** {@code "provider_subtype"} */ + public static final AnalyticsCatalogueGroupDimension PROVIDER_SUBTYPE = new AnalyticsCatalogueGroupDimension("provider_subtype"); + + /** {@code "from_address"} */ + public static final AnalyticsCatalogueGroupDimension FROM_ADDRESS = new AnalyticsCatalogueGroupDimension("from_address"); + + /** {@code "subject"} */ + public static final AnalyticsCatalogueGroupDimension SUBJECT = new AnalyticsCatalogueGroupDimension("subject"); + + /** {@code "dedicated_ip"} */ + public static final AnalyticsCatalogueGroupDimension DEDICATED_IP = new AnalyticsCatalogueGroupDimension("dedicated_ip"); + + /** {@code "dedicated_pool_id"} */ + public static final AnalyticsCatalogueGroupDimension DEDICATED_POOL_ID = new AnalyticsCatalogueGroupDimension("dedicated_pool_id"); + + /** {@code "infrastructure_state"} */ + public static final AnalyticsCatalogueGroupDimension INFRASTRUCTURE_STATE = new AnalyticsCatalogueGroupDimension("infrastructure_state"); + + /** {@code "smtp_code"} */ + public static final AnalyticsCatalogueGroupDimension SMTP_CODE = new AnalyticsCatalogueGroupDimension("smtp_code"); + + /** {@code "enhanced_status_code"} */ + public static final AnalyticsCatalogueGroupDimension ENHANCED_STATUS_CODE = new AnalyticsCatalogueGroupDimension("enhanced_status_code"); + + /** {@code "enhanced_status_category"} */ + public static final AnalyticsCatalogueGroupDimension ENHANCED_STATUS_CATEGORY = new AnalyticsCatalogueGroupDimension("enhanced_status_category"); + + /** {@code "bounce_classification"} */ + public static final AnalyticsCatalogueGroupDimension BOUNCE_CLASSIFICATION = new AnalyticsCatalogueGroupDimension("bounce_classification"); + + /** {@code "failure_reason"} */ + public static final AnalyticsCatalogueGroupDimension FAILURE_REASON = new AnalyticsCatalogueGroupDimension("failure_reason"); + + /** {@code "smtp_response_group"} */ + public static final AnalyticsCatalogueGroupDimension SMTP_RESPONSE_GROUP = new AnalyticsCatalogueGroupDimension("smtp_response_group"); + + /** {@code "engagement_state"} */ + public static final AnalyticsCatalogueGroupDimension ENGAGEMENT_STATE = new AnalyticsCatalogueGroupDimension("engagement_state"); + + /** {@code "request_actor"} */ + public static final AnalyticsCatalogueGroupDimension REQUEST_ACTOR = new AnalyticsCatalogueGroupDimension("request_actor"); + + /** {@code "proxy_type"} */ + public static final AnalyticsCatalogueGroupDimension PROXY_TYPE = new AnalyticsCatalogueGroupDimension("proxy_type"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PROJECT_ID.value, PROJECT_ID); + known.put(ROUTE_ID.value, ROUTE_ID); + known.put(MESSAGE_TYPE.value, MESSAGE_TYPE); + known.put(SENDING_DOMAIN.value, SENDING_DOMAIN); + known.put(RECIPIENT_DOMAIN.value, RECIPIENT_DOMAIN); + known.put(PROVIDER_FAMILY.value, PROVIDER_FAMILY); + known.put(PROVIDER_SUBTYPE.value, PROVIDER_SUBTYPE); + known.put(FROM_ADDRESS.value, FROM_ADDRESS); + known.put(SUBJECT.value, SUBJECT); + known.put(DEDICATED_IP.value, DEDICATED_IP); + known.put(DEDICATED_POOL_ID.value, DEDICATED_POOL_ID); + known.put(INFRASTRUCTURE_STATE.value, INFRASTRUCTURE_STATE); + known.put(SMTP_CODE.value, SMTP_CODE); + known.put(ENHANCED_STATUS_CODE.value, ENHANCED_STATUS_CODE); + known.put(ENHANCED_STATUS_CATEGORY.value, ENHANCED_STATUS_CATEGORY); + known.put(BOUNCE_CLASSIFICATION.value, BOUNCE_CLASSIFICATION); + known.put(FAILURE_REASON.value, FAILURE_REASON); + known.put(SMTP_RESPONSE_GROUP.value, SMTP_RESPONSE_GROUP); + known.put(ENGAGEMENT_STATE.value, ENGAGEMENT_STATE); + known.put(REQUEST_ACTOR.value, REQUEST_ACTOR); + known.put(PROXY_TYPE.value, PROXY_TYPE); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsCatalogueGroupDimension(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsCatalogueGroupDimension of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsCatalogueGroupDimension known = KNOWN.get(value); + return known != null ? known : new AnalyticsCatalogueGroupDimension(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsCatalogueGroupDimension that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsComparison.java b/src/main/java/co/lettermint/types/AnalyticsComparison.java new file mode 100644 index 0000000..97f4da6 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsComparison.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A comparison period. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsComparison { + /** {@code "previous_period"} */ + public static final AnalyticsComparison PREVIOUS_PERIOD = new AnalyticsComparison("previous_period"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PREVIOUS_PERIOD.value, PREVIOUS_PERIOD); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsComparison(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsComparison of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsComparison known = KNOWN.get(value); + return known != null ? known : new AnalyticsComparison(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsComparison that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java b/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java new file mode 100644 index 0000000..152f117 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Metric values for the comparison period. + * + * @param metrics Always present. + * @param rateBases Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsComparisonValues( + @JsonProperty("metrics") AnalyticsMetricValues metrics, + @JsonProperty("rate_bases") AnalyticsRateBases rateBases +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsComparisonValues. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.metrics = metrics; + builder.rateBases = rateBases; + return builder; + } + + /** Builds a {@link AnalyticsComparisonValues}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsMetricValues metrics; + private AnalyticsRateBases rateBases; + + private Builder() { + } + + /** Sets {@code metrics}. */ + public Builder metrics(AnalyticsMetricValues metrics) { + this.metrics = metrics; + return this; + } + + /** Sets {@code rate_bases}. */ + public Builder rateBases(AnalyticsRateBases rateBases) { + this.rateBases = rateBases; + return this; + } + + /** Returns the {@link AnalyticsComparisonValues}. */ + public AnalyticsComparisonValues build() { + return new AnalyticsComparisonValues(metrics, rateBases); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsDimension.java b/src/main/java/co/lettermint/types/AnalyticsDimension.java new file mode 100644 index 0000000..c13186d --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsDimension.java @@ -0,0 +1,178 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A catalogue dimension or tag:<case-sensitive name> to filter by. is_human, is_privacy, is_bot and is_scanner select an engagement class: filter them with the value 1 to restrict engagement metrics to that class. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsDimension { + /** {@code "project_id"} */ + public static final AnalyticsDimension PROJECT_ID = new AnalyticsDimension("project_id"); + + /** {@code "route_id"} */ + public static final AnalyticsDimension ROUTE_ID = new AnalyticsDimension("route_id"); + + /** {@code "message_type"} */ + public static final AnalyticsDimension MESSAGE_TYPE = new AnalyticsDimension("message_type"); + + /** {@code "sending_domain"} */ + public static final AnalyticsDimension SENDING_DOMAIN = new AnalyticsDimension("sending_domain"); + + /** {@code "recipient_domain"} */ + public static final AnalyticsDimension RECIPIENT_DOMAIN = new AnalyticsDimension("recipient_domain"); + + /** {@code "provider_family"} */ + public static final AnalyticsDimension PROVIDER_FAMILY = new AnalyticsDimension("provider_family"); + + /** {@code "provider_subtype"} */ + public static final AnalyticsDimension PROVIDER_SUBTYPE = new AnalyticsDimension("provider_subtype"); + + /** {@code "from_address"} */ + public static final AnalyticsDimension FROM_ADDRESS = new AnalyticsDimension("from_address"); + + /** {@code "subject"} */ + public static final AnalyticsDimension SUBJECT = new AnalyticsDimension("subject"); + + /** {@code "dedicated_ip"} */ + public static final AnalyticsDimension DEDICATED_IP = new AnalyticsDimension("dedicated_ip"); + + /** {@code "dedicated_pool_id"} */ + public static final AnalyticsDimension DEDICATED_POOL_ID = new AnalyticsDimension("dedicated_pool_id"); + + /** {@code "infrastructure_state"} */ + public static final AnalyticsDimension INFRASTRUCTURE_STATE = new AnalyticsDimension("infrastructure_state"); + + /** {@code "smtp_code"} */ + public static final AnalyticsDimension SMTP_CODE = new AnalyticsDimension("smtp_code"); + + /** {@code "enhanced_status_code"} */ + public static final AnalyticsDimension ENHANCED_STATUS_CODE = new AnalyticsDimension("enhanced_status_code"); + + /** {@code "enhanced_status_category"} */ + public static final AnalyticsDimension ENHANCED_STATUS_CATEGORY = new AnalyticsDimension("enhanced_status_category"); + + /** {@code "bounce_classification"} */ + public static final AnalyticsDimension BOUNCE_CLASSIFICATION = new AnalyticsDimension("bounce_classification"); + + /** {@code "failure_reason"} */ + public static final AnalyticsDimension FAILURE_REASON = new AnalyticsDimension("failure_reason"); + + /** {@code "smtp_response_group"} */ + public static final AnalyticsDimension SMTP_RESPONSE_GROUP = new AnalyticsDimension("smtp_response_group"); + + /** {@code "engagement_state"} */ + public static final AnalyticsDimension ENGAGEMENT_STATE = new AnalyticsDimension("engagement_state"); + + /** {@code "request_actor"} */ + public static final AnalyticsDimension REQUEST_ACTOR = new AnalyticsDimension("request_actor"); + + /** {@code "proxy_type"} */ + public static final AnalyticsDimension PROXY_TYPE = new AnalyticsDimension("proxy_type"); + + /** {@code "is_human"} */ + public static final AnalyticsDimension IS_HUMAN = new AnalyticsDimension("is_human"); + + /** {@code "is_privacy"} */ + public static final AnalyticsDimension IS_PRIVACY = new AnalyticsDimension("is_privacy"); + + /** {@code "is_bot"} */ + public static final AnalyticsDimension IS_BOT = new AnalyticsDimension("is_bot"); + + /** {@code "is_scanner"} */ + public static final AnalyticsDimension IS_SCANNER = new AnalyticsDimension("is_scanner"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PROJECT_ID.value, PROJECT_ID); + known.put(ROUTE_ID.value, ROUTE_ID); + known.put(MESSAGE_TYPE.value, MESSAGE_TYPE); + known.put(SENDING_DOMAIN.value, SENDING_DOMAIN); + known.put(RECIPIENT_DOMAIN.value, RECIPIENT_DOMAIN); + known.put(PROVIDER_FAMILY.value, PROVIDER_FAMILY); + known.put(PROVIDER_SUBTYPE.value, PROVIDER_SUBTYPE); + known.put(FROM_ADDRESS.value, FROM_ADDRESS); + known.put(SUBJECT.value, SUBJECT); + known.put(DEDICATED_IP.value, DEDICATED_IP); + known.put(DEDICATED_POOL_ID.value, DEDICATED_POOL_ID); + known.put(INFRASTRUCTURE_STATE.value, INFRASTRUCTURE_STATE); + known.put(SMTP_CODE.value, SMTP_CODE); + known.put(ENHANCED_STATUS_CODE.value, ENHANCED_STATUS_CODE); + known.put(ENHANCED_STATUS_CATEGORY.value, ENHANCED_STATUS_CATEGORY); + known.put(BOUNCE_CLASSIFICATION.value, BOUNCE_CLASSIFICATION); + known.put(FAILURE_REASON.value, FAILURE_REASON); + known.put(SMTP_RESPONSE_GROUP.value, SMTP_RESPONSE_GROUP); + known.put(ENGAGEMENT_STATE.value, ENGAGEMENT_STATE); + known.put(REQUEST_ACTOR.value, REQUEST_ACTOR); + known.put(PROXY_TYPE.value, PROXY_TYPE); + known.put(IS_HUMAN.value, IS_HUMAN); + known.put(IS_PRIVACY.value, IS_PRIVACY); + known.put(IS_BOT.value, IS_BOT); + known.put(IS_SCANNER.value, IS_SCANNER); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsDimension(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsDimension of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsDimension known = KNOWN.get(value); + return known != null ? known : new AnalyticsDimension(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsDimension that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsFilter.java b/src/main/java/co/lettermint/types/AnalyticsFilter.java new file mode 100644 index 0000000..c0b4f8d --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsFilter.java @@ -0,0 +1,80 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A dimension filter. + * + * @param dimension Required. + * @param operator eq requires one value; in and not_in require one or more values; is_null and is_not_null require no values. Required. + * @param values String values to match. Supply one for eq, one or more for in/not_in, and none for null checks. Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsFilter( + @JsonProperty("dimension") AnalyticsDimension dimension, + @JsonProperty("operator") AnalyticsFilterOperator operator, + @JsonProperty("values") List values +) { + /** Copies lists and maps into unmodifiable collections. */ + public AnalyticsFilter { + values = Copies.list(values); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsFilter. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.dimension = dimension; + builder.operator = operator; + builder.values = values; + return builder; + } + + /** Builds a {@link AnalyticsFilter}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsDimension dimension; + private AnalyticsFilterOperator operator; + private List values; + + private Builder() { + } + + /** Sets {@code dimension}. */ + public Builder dimension(AnalyticsDimension dimension) { + this.dimension = dimension; + return this; + } + + /** Sets {@code operator}. */ + public Builder operator(AnalyticsFilterOperator operator) { + this.operator = operator; + return this; + } + + /** Sets {@code values}. */ + public Builder values(List values) { + this.values = values; + return this; + } + + /** Returns the {@link AnalyticsFilter}. */ + public AnalyticsFilter build() { + return new AnalyticsFilter(dimension, operator, values); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java b/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java new file mode 100644 index 0000000..f7abe1d --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A filter operator. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsFilterOperator { + /** {@code "eq"} */ + public static final AnalyticsFilterOperator EQ = new AnalyticsFilterOperator("eq"); + + /** {@code "in"} */ + public static final AnalyticsFilterOperator IN = new AnalyticsFilterOperator("in"); + + /** {@code "not_in"} */ + public static final AnalyticsFilterOperator NOT_IN = new AnalyticsFilterOperator("not_in"); + + /** {@code "is_null"} */ + public static final AnalyticsFilterOperator IS_NULL = new AnalyticsFilterOperator("is_null"); + + /** {@code "is_not_null"} */ + public static final AnalyticsFilterOperator IS_NOT_NULL = new AnalyticsFilterOperator("is_not_null"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(EQ.value, EQ); + known.put(IN.value, IN); + known.put(NOT_IN.value, NOT_IN); + known.put(IS_NULL.value, IS_NULL); + known.put(IS_NOT_NULL.value, IS_NOT_NULL); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsFilterOperator(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsFilterOperator of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsFilterOperator known = KNOWN.get(value); + return known != null ? known : new AnalyticsFilterOperator(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsFilterOperator that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java b/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java new file mode 100644 index 0000000..2179089 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java @@ -0,0 +1,162 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A catalogue dimension or tag:<case-sensitive name> to group breakdown rows by. Engagement class dimensions (is_human, is_privacy, is_bot and is_scanner) can only filter. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsGroupDimension { + /** {@code "project_id"} */ + public static final AnalyticsGroupDimension PROJECT_ID = new AnalyticsGroupDimension("project_id"); + + /** {@code "route_id"} */ + public static final AnalyticsGroupDimension ROUTE_ID = new AnalyticsGroupDimension("route_id"); + + /** {@code "message_type"} */ + public static final AnalyticsGroupDimension MESSAGE_TYPE = new AnalyticsGroupDimension("message_type"); + + /** {@code "sending_domain"} */ + public static final AnalyticsGroupDimension SENDING_DOMAIN = new AnalyticsGroupDimension("sending_domain"); + + /** {@code "recipient_domain"} */ + public static final AnalyticsGroupDimension RECIPIENT_DOMAIN = new AnalyticsGroupDimension("recipient_domain"); + + /** {@code "provider_family"} */ + public static final AnalyticsGroupDimension PROVIDER_FAMILY = new AnalyticsGroupDimension("provider_family"); + + /** {@code "provider_subtype"} */ + public static final AnalyticsGroupDimension PROVIDER_SUBTYPE = new AnalyticsGroupDimension("provider_subtype"); + + /** {@code "from_address"} */ + public static final AnalyticsGroupDimension FROM_ADDRESS = new AnalyticsGroupDimension("from_address"); + + /** {@code "subject"} */ + public static final AnalyticsGroupDimension SUBJECT = new AnalyticsGroupDimension("subject"); + + /** {@code "dedicated_ip"} */ + public static final AnalyticsGroupDimension DEDICATED_IP = new AnalyticsGroupDimension("dedicated_ip"); + + /** {@code "dedicated_pool_id"} */ + public static final AnalyticsGroupDimension DEDICATED_POOL_ID = new AnalyticsGroupDimension("dedicated_pool_id"); + + /** {@code "infrastructure_state"} */ + public static final AnalyticsGroupDimension INFRASTRUCTURE_STATE = new AnalyticsGroupDimension("infrastructure_state"); + + /** {@code "smtp_code"} */ + public static final AnalyticsGroupDimension SMTP_CODE = new AnalyticsGroupDimension("smtp_code"); + + /** {@code "enhanced_status_code"} */ + public static final AnalyticsGroupDimension ENHANCED_STATUS_CODE = new AnalyticsGroupDimension("enhanced_status_code"); + + /** {@code "enhanced_status_category"} */ + public static final AnalyticsGroupDimension ENHANCED_STATUS_CATEGORY = new AnalyticsGroupDimension("enhanced_status_category"); + + /** {@code "bounce_classification"} */ + public static final AnalyticsGroupDimension BOUNCE_CLASSIFICATION = new AnalyticsGroupDimension("bounce_classification"); + + /** {@code "failure_reason"} */ + public static final AnalyticsGroupDimension FAILURE_REASON = new AnalyticsGroupDimension("failure_reason"); + + /** {@code "smtp_response_group"} */ + public static final AnalyticsGroupDimension SMTP_RESPONSE_GROUP = new AnalyticsGroupDimension("smtp_response_group"); + + /** {@code "engagement_state"} */ + public static final AnalyticsGroupDimension ENGAGEMENT_STATE = new AnalyticsGroupDimension("engagement_state"); + + /** {@code "request_actor"} */ + public static final AnalyticsGroupDimension REQUEST_ACTOR = new AnalyticsGroupDimension("request_actor"); + + /** {@code "proxy_type"} */ + public static final AnalyticsGroupDimension PROXY_TYPE = new AnalyticsGroupDimension("proxy_type"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PROJECT_ID.value, PROJECT_ID); + known.put(ROUTE_ID.value, ROUTE_ID); + known.put(MESSAGE_TYPE.value, MESSAGE_TYPE); + known.put(SENDING_DOMAIN.value, SENDING_DOMAIN); + known.put(RECIPIENT_DOMAIN.value, RECIPIENT_DOMAIN); + known.put(PROVIDER_FAMILY.value, PROVIDER_FAMILY); + known.put(PROVIDER_SUBTYPE.value, PROVIDER_SUBTYPE); + known.put(FROM_ADDRESS.value, FROM_ADDRESS); + known.put(SUBJECT.value, SUBJECT); + known.put(DEDICATED_IP.value, DEDICATED_IP); + known.put(DEDICATED_POOL_ID.value, DEDICATED_POOL_ID); + known.put(INFRASTRUCTURE_STATE.value, INFRASTRUCTURE_STATE); + known.put(SMTP_CODE.value, SMTP_CODE); + known.put(ENHANCED_STATUS_CODE.value, ENHANCED_STATUS_CODE); + known.put(ENHANCED_STATUS_CATEGORY.value, ENHANCED_STATUS_CATEGORY); + known.put(BOUNCE_CLASSIFICATION.value, BOUNCE_CLASSIFICATION); + known.put(FAILURE_REASON.value, FAILURE_REASON); + known.put(SMTP_RESPONSE_GROUP.value, SMTP_RESPONSE_GROUP); + known.put(ENGAGEMENT_STATE.value, ENGAGEMENT_STATE); + known.put(REQUEST_ACTOR.value, REQUEST_ACTOR); + known.put(PROXY_TYPE.value, PROXY_TYPE); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsGroupDimension(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsGroupDimension of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsGroupDimension known = KNOWN.get(value); + return known != null ? known : new AnalyticsGroupDimension(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsGroupDimension that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsInterval.java b/src/main/java/co/lettermint/types/AnalyticsInterval.java new file mode 100644 index 0000000..f0bd87e --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsInterval.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A time-series bucket size. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsInterval { + /** {@code "hour"} */ + public static final AnalyticsInterval HOUR = new AnalyticsInterval("hour"); + + /** {@code "day"} */ + public static final AnalyticsInterval DAY = new AnalyticsInterval("day"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(HOUR.value, HOUR); + known.put(DAY.value, DAY); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsInterval(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsInterval of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsInterval known = KNOWN.get(value); + return known != null ? known : new AnalyticsInterval(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsInterval that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMeta.java b/src/main/java/co/lettermint/types/AnalyticsMeta.java new file mode 100644 index 0000000..8a6c883 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMeta.java @@ -0,0 +1,210 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The time window and data availability of the results. + * + * @param timeBasis Always present. + * @param timezone Always present. + * @param interval Always present. + * @param from Start of the window read, aligned down to the alignment grain. Always present. + * @param to Exclusive end of the window, aligned up to the alignment grain. Always present. + * @param effectiveTo Exclusive end of the counted data: to, or generated_at while the window is ongoing. Always present. + * @param alignment Grain the requested boundaries were widened to: whole UTC hours, or whole UTC days for personal-data dimensions. Counts cover exactly from to effective_to. Always present. + * @param generatedAt Always present. + * @param availableSince Always present. + * @param partial Always present. + * @param ongoing Always present. + * @param collectionCompleteness Always present. + * @param lastIngestedAt Latest ingestion among matching rollup rows. This is not a completeness watermark. Always present; may be null. + * @param metricDefinitionVersion Always present. + * @param rankedGroupLimit Always present. + * @param comparison Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsMeta( + @JsonProperty("time_basis") AnalyticsMetaTimeBasis timeBasis, + @JsonProperty("timezone") String timezone, + @JsonProperty("interval") AnalyticsInterval interval, + @JsonProperty("from") String from, + @JsonProperty("to") String to, + @JsonProperty("effective_to") String effectiveTo, + @JsonProperty("alignment") AnalyticsMetaAlignment alignment, + @JsonProperty("generated_at") String generatedAt, + @JsonProperty("available_since") String availableSince, + @JsonProperty("partial") Boolean partial, + @JsonProperty("ongoing") Boolean ongoing, + @JsonProperty("collection_completeness") AnalyticsMetaCollectionCompleteness collectionCompleteness, + @JsonProperty("last_ingested_at") String lastIngestedAt, + @JsonProperty("metric_definition_version") String metricDefinitionVersion, + @JsonProperty("ranked_group_limit") Long rankedGroupLimit, + @JsonProperty("comparison") AnalyticsMetaComparison comparison +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsMeta. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.timeBasis = timeBasis; + builder.timezone = timezone; + builder.interval = interval; + builder.from = from; + builder.to = to; + builder.effectiveTo = effectiveTo; + builder.alignment = alignment; + builder.generatedAt = generatedAt; + builder.availableSince = availableSince; + builder.partial = partial; + builder.ongoing = ongoing; + builder.collectionCompleteness = collectionCompleteness; + builder.lastIngestedAt = lastIngestedAt; + builder.metricDefinitionVersion = metricDefinitionVersion; + builder.rankedGroupLimit = rankedGroupLimit; + builder.comparison = comparison; + return builder; + } + + /** Builds a {@link AnalyticsMeta}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsMetaTimeBasis timeBasis; + private String timezone; + private AnalyticsInterval interval; + private String from; + private String to; + private String effectiveTo; + private AnalyticsMetaAlignment alignment; + private String generatedAt; + private String availableSince; + private Boolean partial; + private Boolean ongoing; + private AnalyticsMetaCollectionCompleteness collectionCompleteness; + private String lastIngestedAt; + private String metricDefinitionVersion; + private Long rankedGroupLimit; + private AnalyticsMetaComparison comparison; + + private Builder() { + } + + /** Sets {@code time_basis}. */ + public Builder timeBasis(AnalyticsMetaTimeBasis timeBasis) { + this.timeBasis = timeBasis; + return this; + } + + /** Sets {@code timezone}. */ + public Builder timezone(String timezone) { + this.timezone = timezone; + return this; + } + + /** Sets {@code interval}. */ + public Builder interval(AnalyticsInterval interval) { + this.interval = interval; + return this; + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(String to) { + this.to = to; + return this; + } + + /** Sets {@code effective_to}. */ + public Builder effectiveTo(String effectiveTo) { + this.effectiveTo = effectiveTo; + return this; + } + + /** Sets {@code alignment}. */ + public Builder alignment(AnalyticsMetaAlignment alignment) { + this.alignment = alignment; + return this; + } + + /** Sets {@code generated_at}. */ + public Builder generatedAt(String generatedAt) { + this.generatedAt = generatedAt; + return this; + } + + /** Sets {@code available_since}. */ + public Builder availableSince(String availableSince) { + this.availableSince = availableSince; + return this; + } + + /** Sets {@code partial}. */ + public Builder partial(Boolean partial) { + this.partial = partial; + return this; + } + + /** Sets {@code ongoing}. */ + public Builder ongoing(Boolean ongoing) { + this.ongoing = ongoing; + return this; + } + + /** Sets {@code collection_completeness}. */ + public Builder collectionCompleteness(AnalyticsMetaCollectionCompleteness collectionCompleteness) { + this.collectionCompleteness = collectionCompleteness; + return this; + } + + /** Sets {@code last_ingested_at}. */ + public Builder lastIngestedAt(String lastIngestedAt) { + this.lastIngestedAt = lastIngestedAt; + return this; + } + + /** Sets {@code metric_definition_version}. */ + public Builder metricDefinitionVersion(String metricDefinitionVersion) { + this.metricDefinitionVersion = metricDefinitionVersion; + return this; + } + + /** Sets {@code ranked_group_limit}. */ + public Builder rankedGroupLimit(Long rankedGroupLimit) { + this.rankedGroupLimit = rankedGroupLimit; + return this; + } + + /** Sets {@code ranked_group_limit}. */ + public Builder rankedGroupLimit(long rankedGroupLimit) { + this.rankedGroupLimit = rankedGroupLimit; + return this; + } + + /** Sets {@code comparison}. */ + public Builder comparison(AnalyticsMetaComparison comparison) { + this.comparison = comparison; + return this; + } + + /** Returns the {@link AnalyticsMeta}. */ + public AnalyticsMeta build() { + return new AnalyticsMeta(timeBasis, timezone, interval, from, to, effectiveTo, alignment, generatedAt, availableSince, partial, ongoing, collectionCompleteness, lastIngestedAt, metricDefinitionVersion, rankedGroupLimit, comparison); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java b/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java new file mode 100644 index 0000000..857464d --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Grain the requested boundaries were widened to: whole UTC hours, or whole UTC days for personal-data dimensions. Counts cover exactly from to effective_to. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsMetaAlignment { + /** {@code "hour"} */ + public static final AnalyticsMetaAlignment HOUR = new AnalyticsMetaAlignment("hour"); + + /** {@code "day"} */ + public static final AnalyticsMetaAlignment DAY = new AnalyticsMetaAlignment("day"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(HOUR.value, HOUR); + known.put(DAY.value, DAY); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsMetaAlignment(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsMetaAlignment of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsMetaAlignment known = KNOWN.get(value); + return known != null ? known : new AnalyticsMetaAlignment(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsMetaAlignment that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java b/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java new file mode 100644 index 0000000..e781853 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java @@ -0,0 +1,78 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class AnalyticsMetaCollectionCompleteness { + /** {@code "best_effort"} */ + public static final AnalyticsMetaCollectionCompleteness BEST_EFFORT = new AnalyticsMetaCollectionCompleteness("best_effort"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(BEST_EFFORT.value, BEST_EFFORT); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsMetaCollectionCompleteness(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsMetaCollectionCompleteness of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsMetaCollectionCompleteness known = KNOWN.get(value); + return known != null ? known : new AnalyticsMetaCollectionCompleteness(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsMetaCollectionCompleteness that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java b/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java new file mode 100644 index 0000000..ed5fbe7 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java @@ -0,0 +1,72 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param from Always present. + * @param to Always present. + * @param partial Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsMetaComparison( + @JsonProperty("from") String from, + @JsonProperty("to") String to, + @JsonProperty("partial") Boolean partial +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsMetaComparison. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.from = from; + builder.to = to; + builder.partial = partial; + return builder; + } + + /** Builds a {@link AnalyticsMetaComparison}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String from; + private String to; + private Boolean partial; + + private Builder() { + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(String to) { + this.to = to; + return this; + } + + /** Sets {@code partial}. */ + public Builder partial(Boolean partial) { + this.partial = partial; + return this; + } + + /** Returns the {@link AnalyticsMetaComparison}. */ + public AnalyticsMetaComparison build() { + return new AnalyticsMetaComparison(from, to, partial); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java b/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java new file mode 100644 index 0000000..802d1fc --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java @@ -0,0 +1,78 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class AnalyticsMetaTimeBasis { + /** {@code "event"} */ + public static final AnalyticsMetaTimeBasis EVENT = new AnalyticsMetaTimeBasis("event"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(EVENT.value, EVENT); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsMetaTimeBasis(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsMetaTimeBasis of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsMetaTimeBasis known = KNOWN.get(value); + return known != null ? known : new AnalyticsMetaTimeBasis(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsMetaTimeBasis that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetric.java b/src/main/java/co/lettermint/types/AnalyticsMetric.java new file mode 100644 index 0000000..f6ed902 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetric.java @@ -0,0 +1,346 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A metric from the analytics catalogue. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsMetric { + /** {@code "accepted"} */ + public static final AnalyticsMetric ACCEPTED = new AnalyticsMetric("accepted"); + + /** {@code "processed"} */ + public static final AnalyticsMetric PROCESSED = new AnalyticsMetric("processed"); + + /** {@code "suppressed"} */ + public static final AnalyticsMetric SUPPRESSED = new AnalyticsMetric("suppressed"); + + /** {@code "policy_rejected"} */ + public static final AnalyticsMetric POLICY_REJECTED = new AnalyticsMetric("policy_rejected"); + + /** {@code "application_failed"} */ + public static final AnalyticsMetric APPLICATION_FAILED = new AnalyticsMetric("application_failed"); + + /** {@code "mta_accepted"} */ + public static final AnalyticsMetric MTA_ACCEPTED = new AnalyticsMetric("mta_accepted"); + + /** {@code "canceled"} */ + public static final AnalyticsMetric CANCELED = new AnalyticsMetric("canceled"); + + /** {@code "messages"} */ + public static final AnalyticsMetric MESSAGES = new AnalyticsMetric("messages"); + + /** {@code "delivered"} */ + public static final AnalyticsMetric DELIVERED = new AnalyticsMetric("delivered"); + + /** {@code "bounced"} */ + public static final AnalyticsMetric BOUNCED = new AnalyticsMetric("bounced"); + + /** {@code "soft_bounced"} */ + public static final AnalyticsMetric SOFT_BOUNCED = new AnalyticsMetric("soft_bounced"); + + /** {@code "administratively_bounced"} */ + public static final AnalyticsMetric ADMINISTRATIVELY_BOUNCED = new AnalyticsMetric("administratively_bounced"); + + /** {@code "deferred_recipients"} */ + public static final AnalyticsMetric DEFERRED_RECIPIENTS = new AnalyticsMetric("deferred_recipients"); + + /** {@code "deferred_events"} */ + public static final AnalyticsMetric DEFERRED_EVENTS = new AnalyticsMetric("deferred_events"); + + /** {@code "delivery_attempts"} */ + public static final AnalyticsMetric DELIVERY_ATTEMPTS = new AnalyticsMetric("delivery_attempts"); + + /** {@code "attempted_recipients"} */ + public static final AnalyticsMetric ATTEMPTED_RECIPIENTS = new AnalyticsMetric("attempted_recipients"); + + /** {@code "transport_outcome_recipients"} */ + public static final AnalyticsMetric TRANSPORT_OUTCOME_RECIPIENTS = new AnalyticsMetric("transport_outcome_recipients"); + + /** {@code "effective_delivered"} */ + public static final AnalyticsMetric EFFECTIVE_DELIVERED = new AnalyticsMetric("effective_delivered"); + + /** {@code "open_tracked_delivered"} */ + public static final AnalyticsMetric OPEN_TRACKED_DELIVERED = new AnalyticsMetric("open_tracked_delivered"); + + /** {@code "click_tracked_delivered"} */ + public static final AnalyticsMetric CLICK_TRACKED_DELIVERED = new AnalyticsMetric("click_tracked_delivered"); + + /** {@code "out_of_band_bounced_recipients"} */ + public static final AnalyticsMetric OUT_OF_BAND_BOUNCED_RECIPIENTS = new AnalyticsMetric("out_of_band_bounced_recipients"); + + /** {@code "out_of_band_bounce_events"} */ + public static final AnalyticsMetric OUT_OF_BAND_BOUNCE_EVENTS = new AnalyticsMetric("out_of_band_bounce_events"); + + /** {@code "complained"} */ + public static final AnalyticsMetric COMPLAINED = new AnalyticsMetric("complained"); + + /** {@code "unsubscribed"} */ + public static final AnalyticsMetric UNSUBSCRIBED = new AnalyticsMetric("unsubscribed"); + + /** {@code "human_opens"} */ + public static final AnalyticsMetric HUMAN_OPENS = new AnalyticsMetric("human_opens"); + + /** {@code "human_opens_events"} */ + public static final AnalyticsMetric HUMAN_OPENS_EVENTS = new AnalyticsMetric("human_opens_events"); + + /** {@code "human_clicks"} */ + public static final AnalyticsMetric HUMAN_CLICKS = new AnalyticsMetric("human_clicks"); + + /** {@code "human_clicks_events"} */ + public static final AnalyticsMetric HUMAN_CLICKS_EVENTS = new AnalyticsMetric("human_clicks_events"); + + /** {@code "machine_opens"} */ + public static final AnalyticsMetric MACHINE_OPENS = new AnalyticsMetric("machine_opens"); + + /** {@code "machine_opens_events"} */ + public static final AnalyticsMetric MACHINE_OPENS_EVENTS = new AnalyticsMetric("machine_opens_events"); + + /** {@code "machine_clicks"} */ + public static final AnalyticsMetric MACHINE_CLICKS = new AnalyticsMetric("machine_clicks"); + + /** {@code "machine_clicks_events"} */ + public static final AnalyticsMetric MACHINE_CLICKS_EVENTS = new AnalyticsMetric("machine_clicks_events"); + + /** {@code "privacy_opens"} */ + public static final AnalyticsMetric PRIVACY_OPENS = new AnalyticsMetric("privacy_opens"); + + /** {@code "privacy_opens_events"} */ + public static final AnalyticsMetric PRIVACY_OPENS_EVENTS = new AnalyticsMetric("privacy_opens_events"); + + /** {@code "privacy_clicks"} */ + public static final AnalyticsMetric PRIVACY_CLICKS = new AnalyticsMetric("privacy_clicks"); + + /** {@code "privacy_clicks_events"} */ + public static final AnalyticsMetric PRIVACY_CLICKS_EVENTS = new AnalyticsMetric("privacy_clicks_events"); + + /** {@code "bot_opens"} */ + public static final AnalyticsMetric BOT_OPENS = new AnalyticsMetric("bot_opens"); + + /** {@code "bot_opens_events"} */ + public static final AnalyticsMetric BOT_OPENS_EVENTS = new AnalyticsMetric("bot_opens_events"); + + /** {@code "bot_clicks"} */ + public static final AnalyticsMetric BOT_CLICKS = new AnalyticsMetric("bot_clicks"); + + /** {@code "bot_clicks_events"} */ + public static final AnalyticsMetric BOT_CLICKS_EVENTS = new AnalyticsMetric("bot_clicks_events"); + + /** {@code "scanner_opens"} */ + public static final AnalyticsMetric SCANNER_OPENS = new AnalyticsMetric("scanner_opens"); + + /** {@code "scanner_opens_events"} */ + public static final AnalyticsMetric SCANNER_OPENS_EVENTS = new AnalyticsMetric("scanner_opens_events"); + + /** {@code "scanner_clicks"} */ + public static final AnalyticsMetric SCANNER_CLICKS = new AnalyticsMetric("scanner_clicks"); + + /** {@code "scanner_clicks_events"} */ + public static final AnalyticsMetric SCANNER_CLICKS_EVENTS = new AnalyticsMetric("scanner_clicks_events"); + + /** {@code "observed_opens"} */ + public static final AnalyticsMetric OBSERVED_OPENS = new AnalyticsMetric("observed_opens"); + + /** {@code "observed_opens_events"} */ + public static final AnalyticsMetric OBSERVED_OPENS_EVENTS = new AnalyticsMetric("observed_opens_events"); + + /** {@code "observed_clicks"} */ + public static final AnalyticsMetric OBSERVED_CLICKS = new AnalyticsMetric("observed_clicks"); + + /** {@code "observed_clicks_events"} */ + public static final AnalyticsMetric OBSERVED_CLICKS_EVENTS = new AnalyticsMetric("observed_clicks_events"); + + /** {@code "delivery_rate"} */ + public static final AnalyticsMetric DELIVERY_RATE = new AnalyticsMetric("delivery_rate"); + + /** {@code "effective_delivery_rate"} */ + public static final AnalyticsMetric EFFECTIVE_DELIVERY_RATE = new AnalyticsMetric("effective_delivery_rate"); + + /** {@code "bounce_rate"} */ + public static final AnalyticsMetric BOUNCE_RATE = new AnalyticsMetric("bounce_rate"); + + /** {@code "deferral_rate"} */ + public static final AnalyticsMetric DEFERRAL_RATE = new AnalyticsMetric("deferral_rate"); + + /** {@code "complaint_rate"} */ + public static final AnalyticsMetric COMPLAINT_RATE = new AnalyticsMetric("complaint_rate"); + + /** {@code "human_open_rate"} */ + public static final AnalyticsMetric HUMAN_OPEN_RATE = new AnalyticsMetric("human_open_rate"); + + /** {@code "human_click_rate"} */ + public static final AnalyticsMetric HUMAN_CLICK_RATE = new AnalyticsMetric("human_click_rate"); + + /** {@code "processing_latency_p50_ms"} */ + public static final AnalyticsMetric PROCESSING_LATENCY_P50_MS = new AnalyticsMetric("processing_latency_p50_ms"); + + /** {@code "processing_latency_p95_ms"} */ + public static final AnalyticsMetric PROCESSING_LATENCY_P95_MS = new AnalyticsMetric("processing_latency_p95_ms"); + + /** {@code "processing_latency_p99_ms"} */ + public static final AnalyticsMetric PROCESSING_LATENCY_P99_MS = new AnalyticsMetric("processing_latency_p99_ms"); + + /** {@code "processing_latency_samples"} */ + public static final AnalyticsMetric PROCESSING_LATENCY_SAMPLES = new AnalyticsMetric("processing_latency_samples"); + + /** {@code "delivery_latency_p50_ms"} */ + public static final AnalyticsMetric DELIVERY_LATENCY_P50_MS = new AnalyticsMetric("delivery_latency_p50_ms"); + + /** {@code "delivery_latency_p95_ms"} */ + public static final AnalyticsMetric DELIVERY_LATENCY_P95_MS = new AnalyticsMetric("delivery_latency_p95_ms"); + + /** {@code "delivery_latency_p99_ms"} */ + public static final AnalyticsMetric DELIVERY_LATENCY_P99_MS = new AnalyticsMetric("delivery_latency_p99_ms"); + + /** {@code "delivery_latency_samples"} */ + public static final AnalyticsMetric DELIVERY_LATENCY_SAMPLES = new AnalyticsMetric("delivery_latency_samples"); + + /** {@code "total_latency_p50_ms"} */ + public static final AnalyticsMetric TOTAL_LATENCY_P50_MS = new AnalyticsMetric("total_latency_p50_ms"); + + /** {@code "total_latency_p95_ms"} */ + public static final AnalyticsMetric TOTAL_LATENCY_P95_MS = new AnalyticsMetric("total_latency_p95_ms"); + + /** {@code "total_latency_p99_ms"} */ + public static final AnalyticsMetric TOTAL_LATENCY_P99_MS = new AnalyticsMetric("total_latency_p99_ms"); + + /** {@code "total_latency_samples"} */ + public static final AnalyticsMetric TOTAL_LATENCY_SAMPLES = new AnalyticsMetric("total_latency_samples"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(ACCEPTED.value, ACCEPTED); + known.put(PROCESSED.value, PROCESSED); + known.put(SUPPRESSED.value, SUPPRESSED); + known.put(POLICY_REJECTED.value, POLICY_REJECTED); + known.put(APPLICATION_FAILED.value, APPLICATION_FAILED); + known.put(MTA_ACCEPTED.value, MTA_ACCEPTED); + known.put(CANCELED.value, CANCELED); + known.put(MESSAGES.value, MESSAGES); + known.put(DELIVERED.value, DELIVERED); + known.put(BOUNCED.value, BOUNCED); + known.put(SOFT_BOUNCED.value, SOFT_BOUNCED); + known.put(ADMINISTRATIVELY_BOUNCED.value, ADMINISTRATIVELY_BOUNCED); + known.put(DEFERRED_RECIPIENTS.value, DEFERRED_RECIPIENTS); + known.put(DEFERRED_EVENTS.value, DEFERRED_EVENTS); + known.put(DELIVERY_ATTEMPTS.value, DELIVERY_ATTEMPTS); + known.put(ATTEMPTED_RECIPIENTS.value, ATTEMPTED_RECIPIENTS); + known.put(TRANSPORT_OUTCOME_RECIPIENTS.value, TRANSPORT_OUTCOME_RECIPIENTS); + known.put(EFFECTIVE_DELIVERED.value, EFFECTIVE_DELIVERED); + known.put(OPEN_TRACKED_DELIVERED.value, OPEN_TRACKED_DELIVERED); + known.put(CLICK_TRACKED_DELIVERED.value, CLICK_TRACKED_DELIVERED); + known.put(OUT_OF_BAND_BOUNCED_RECIPIENTS.value, OUT_OF_BAND_BOUNCED_RECIPIENTS); + known.put(OUT_OF_BAND_BOUNCE_EVENTS.value, OUT_OF_BAND_BOUNCE_EVENTS); + known.put(COMPLAINED.value, COMPLAINED); + known.put(UNSUBSCRIBED.value, UNSUBSCRIBED); + known.put(HUMAN_OPENS.value, HUMAN_OPENS); + known.put(HUMAN_OPENS_EVENTS.value, HUMAN_OPENS_EVENTS); + known.put(HUMAN_CLICKS.value, HUMAN_CLICKS); + known.put(HUMAN_CLICKS_EVENTS.value, HUMAN_CLICKS_EVENTS); + known.put(MACHINE_OPENS.value, MACHINE_OPENS); + known.put(MACHINE_OPENS_EVENTS.value, MACHINE_OPENS_EVENTS); + known.put(MACHINE_CLICKS.value, MACHINE_CLICKS); + known.put(MACHINE_CLICKS_EVENTS.value, MACHINE_CLICKS_EVENTS); + known.put(PRIVACY_OPENS.value, PRIVACY_OPENS); + known.put(PRIVACY_OPENS_EVENTS.value, PRIVACY_OPENS_EVENTS); + known.put(PRIVACY_CLICKS.value, PRIVACY_CLICKS); + known.put(PRIVACY_CLICKS_EVENTS.value, PRIVACY_CLICKS_EVENTS); + known.put(BOT_OPENS.value, BOT_OPENS); + known.put(BOT_OPENS_EVENTS.value, BOT_OPENS_EVENTS); + known.put(BOT_CLICKS.value, BOT_CLICKS); + known.put(BOT_CLICKS_EVENTS.value, BOT_CLICKS_EVENTS); + known.put(SCANNER_OPENS.value, SCANNER_OPENS); + known.put(SCANNER_OPENS_EVENTS.value, SCANNER_OPENS_EVENTS); + known.put(SCANNER_CLICKS.value, SCANNER_CLICKS); + known.put(SCANNER_CLICKS_EVENTS.value, SCANNER_CLICKS_EVENTS); + known.put(OBSERVED_OPENS.value, OBSERVED_OPENS); + known.put(OBSERVED_OPENS_EVENTS.value, OBSERVED_OPENS_EVENTS); + known.put(OBSERVED_CLICKS.value, OBSERVED_CLICKS); + known.put(OBSERVED_CLICKS_EVENTS.value, OBSERVED_CLICKS_EVENTS); + known.put(DELIVERY_RATE.value, DELIVERY_RATE); + known.put(EFFECTIVE_DELIVERY_RATE.value, EFFECTIVE_DELIVERY_RATE); + known.put(BOUNCE_RATE.value, BOUNCE_RATE); + known.put(DEFERRAL_RATE.value, DEFERRAL_RATE); + known.put(COMPLAINT_RATE.value, COMPLAINT_RATE); + known.put(HUMAN_OPEN_RATE.value, HUMAN_OPEN_RATE); + known.put(HUMAN_CLICK_RATE.value, HUMAN_CLICK_RATE); + known.put(PROCESSING_LATENCY_P50_MS.value, PROCESSING_LATENCY_P50_MS); + known.put(PROCESSING_LATENCY_P95_MS.value, PROCESSING_LATENCY_P95_MS); + known.put(PROCESSING_LATENCY_P99_MS.value, PROCESSING_LATENCY_P99_MS); + known.put(PROCESSING_LATENCY_SAMPLES.value, PROCESSING_LATENCY_SAMPLES); + known.put(DELIVERY_LATENCY_P50_MS.value, DELIVERY_LATENCY_P50_MS); + known.put(DELIVERY_LATENCY_P95_MS.value, DELIVERY_LATENCY_P95_MS); + known.put(DELIVERY_LATENCY_P99_MS.value, DELIVERY_LATENCY_P99_MS); + known.put(DELIVERY_LATENCY_SAMPLES.value, DELIVERY_LATENCY_SAMPLES); + known.put(TOTAL_LATENCY_P50_MS.value, TOTAL_LATENCY_P50_MS); + known.put(TOTAL_LATENCY_P95_MS.value, TOTAL_LATENCY_P95_MS); + known.put(TOTAL_LATENCY_P99_MS.value, TOTAL_LATENCY_P99_MS); + known.put(TOTAL_LATENCY_SAMPLES.value, TOTAL_LATENCY_SAMPLES); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsMetric(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsMetric of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsMetric known = KNOWN.get(value); + return known != null ? known : new AnalyticsMetric(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsMetric that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetricChange.java b/src/main/java/co/lettermint/types/AnalyticsMetricChange.java new file mode 100644 index 0000000..c25153e --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetricChange.java @@ -0,0 +1,92 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Change of a metric against the comparison period. + * + * @param absolute Optional and nullable: null when absent or null. + * @param relative Optional and nullable: null when absent or null. + * @param percentagePoints Optional and nullable: null when absent or null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsMetricChange( + @JsonProperty("absolute") Double absolute, + @JsonProperty("relative") Double relative, + @JsonProperty("percentage_points") Double percentagePoints +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsMetricChange. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.absolute = absolute; + builder.relative = relative; + builder.percentagePoints = percentagePoints; + return builder; + } + + /** Builds a {@link AnalyticsMetricChange}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Double absolute; + private Double relative; + private Double percentagePoints; + + private Builder() { + } + + /** Sets {@code absolute}. */ + public Builder absolute(Double absolute) { + this.absolute = absolute; + return this; + } + + /** Sets {@code absolute}. */ + public Builder absolute(double absolute) { + this.absolute = absolute; + return this; + } + + /** Sets {@code relative}. */ + public Builder relative(Double relative) { + this.relative = relative; + return this; + } + + /** Sets {@code relative}. */ + public Builder relative(double relative) { + this.relative = relative; + return this; + } + + /** Sets {@code percentage_points}. */ + public Builder percentagePoints(Double percentagePoints) { + this.percentagePoints = percentagePoints; + return this; + } + + /** Sets {@code percentage_points}. */ + public Builder percentagePoints(double percentagePoints) { + this.percentagePoints = percentagePoints; + return this; + } + + /** Returns the {@link AnalyticsMetricChange}. */ + public AnalyticsMetricChange build() { + return new AnalyticsMetricChange(absolute, relative, percentagePoints); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsMetricValues.java b/src/main/java/co/lettermint/types/AnalyticsMetricValues.java new file mode 100644 index 0000000..7f099b1 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsMetricValues.java @@ -0,0 +1,1116 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Values of the selected metrics. Rates are fractions; null when not available. + * + * @param accepted Optional and nullable: null when absent or null. + * @param processed Optional and nullable: null when absent or null. + * @param suppressed Optional and nullable: null when absent or null. + * @param policyRejected Optional and nullable: null when absent or null. + * @param applicationFailed Optional and nullable: null when absent or null. + * @param mtaAccepted Optional and nullable: null when absent or null. + * @param canceled Optional and nullable: null when absent or null. + * @param messages Optional and nullable: null when absent or null. + * @param delivered Optional and nullable: null when absent or null. + * @param bounced Optional and nullable: null when absent or null. + * @param softBounced Optional and nullable: null when absent or null. + * @param administrativelyBounced Optional and nullable: null when absent or null. + * @param deferredRecipients Optional and nullable: null when absent or null. + * @param deferredEvents Optional and nullable: null when absent or null. + * @param deliveryAttempts Optional and nullable: null when absent or null. + * @param attemptedRecipients Optional and nullable: null when absent or null. + * @param transportOutcomeRecipients Optional and nullable: null when absent or null. + * @param effectiveDelivered Optional and nullable: null when absent or null. + * @param openTrackedDelivered Optional and nullable: null when absent or null. + * @param clickTrackedDelivered Optional and nullable: null when absent or null. + * @param outOfBandBouncedRecipients Optional and nullable: null when absent or null. + * @param outOfBandBounceEvents Optional and nullable: null when absent or null. + * @param complained Optional and nullable: null when absent or null. + * @param unsubscribed Optional and nullable: null when absent or null. + * @param humanOpens Optional and nullable: null when absent or null. + * @param humanOpensEvents Optional and nullable: null when absent or null. + * @param humanClicks Optional and nullable: null when absent or null. + * @param humanClicksEvents Optional and nullable: null when absent or null. + * @param machineOpens Optional and nullable: null when absent or null. + * @param machineOpensEvents Optional and nullable: null when absent or null. + * @param machineClicks Optional and nullable: null when absent or null. + * @param machineClicksEvents Optional and nullable: null when absent or null. + * @param privacyOpens Optional and nullable: null when absent or null. + * @param privacyOpensEvents Optional and nullable: null when absent or null. + * @param privacyClicks Optional and nullable: null when absent or null. + * @param privacyClicksEvents Optional and nullable: null when absent or null. + * @param botOpens Optional and nullable: null when absent or null. + * @param botOpensEvents Optional and nullable: null when absent or null. + * @param botClicks Optional and nullable: null when absent or null. + * @param botClicksEvents Optional and nullable: null when absent or null. + * @param scannerOpens Optional and nullable: null when absent or null. + * @param scannerOpensEvents Optional and nullable: null when absent or null. + * @param scannerClicks Optional and nullable: null when absent or null. + * @param scannerClicksEvents Optional and nullable: null when absent or null. + * @param observedOpens Optional and nullable: null when absent or null. + * @param observedOpensEvents Optional and nullable: null when absent or null. + * @param observedClicks Optional and nullable: null when absent or null. + * @param observedClicksEvents Optional and nullable: null when absent or null. + * @param deliveryRate Optional and nullable: null when absent or null. + * @param effectiveDeliveryRate Optional and nullable: null when absent or null. + * @param bounceRate Optional and nullable: null when absent or null. + * @param deferralRate Optional and nullable: null when absent or null. + * @param complaintRate Optional and nullable: null when absent or null. + * @param humanOpenRate Optional and nullable: null when absent or null. + * @param humanClickRate Optional and nullable: null when absent or null. + * @param processingLatencyP50Ms Optional and nullable: null when absent or null. + * @param processingLatencyP95Ms Optional and nullable: null when absent or null. + * @param processingLatencyP99Ms Optional and nullable: null when absent or null. + * @param processingLatencySamples Optional and nullable: null when absent or null. + * @param deliveryLatencyP50Ms Optional and nullable: null when absent or null. + * @param deliveryLatencyP95Ms Optional and nullable: null when absent or null. + * @param deliveryLatencyP99Ms Optional and nullable: null when absent or null. + * @param deliveryLatencySamples Optional and nullable: null when absent or null. + * @param totalLatencyP50Ms Optional and nullable: null when absent or null. + * @param totalLatencyP95Ms Optional and nullable: null when absent or null. + * @param totalLatencyP99Ms Optional and nullable: null when absent or null. + * @param totalLatencySamples Optional and nullable: null when absent or null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsMetricValues( + @JsonProperty("accepted") Long accepted, + @JsonProperty("processed") Long processed, + @JsonProperty("suppressed") Long suppressed, + @JsonProperty("policy_rejected") Long policyRejected, + @JsonProperty("application_failed") Long applicationFailed, + @JsonProperty("mta_accepted") Long mtaAccepted, + @JsonProperty("canceled") Long canceled, + @JsonProperty("messages") Long messages, + @JsonProperty("delivered") Long delivered, + @JsonProperty("bounced") Long bounced, + @JsonProperty("soft_bounced") Long softBounced, + @JsonProperty("administratively_bounced") Long administrativelyBounced, + @JsonProperty("deferred_recipients") Long deferredRecipients, + @JsonProperty("deferred_events") Long deferredEvents, + @JsonProperty("delivery_attempts") Long deliveryAttempts, + @JsonProperty("attempted_recipients") Long attemptedRecipients, + @JsonProperty("transport_outcome_recipients") Long transportOutcomeRecipients, + @JsonProperty("effective_delivered") Long effectiveDelivered, + @JsonProperty("open_tracked_delivered") Long openTrackedDelivered, + @JsonProperty("click_tracked_delivered") Long clickTrackedDelivered, + @JsonProperty("out_of_band_bounced_recipients") Long outOfBandBouncedRecipients, + @JsonProperty("out_of_band_bounce_events") Long outOfBandBounceEvents, + @JsonProperty("complained") Long complained, + @JsonProperty("unsubscribed") Long unsubscribed, + @JsonProperty("human_opens") Long humanOpens, + @JsonProperty("human_opens_events") Long humanOpensEvents, + @JsonProperty("human_clicks") Long humanClicks, + @JsonProperty("human_clicks_events") Long humanClicksEvents, + @JsonProperty("machine_opens") Long machineOpens, + @JsonProperty("machine_opens_events") Long machineOpensEvents, + @JsonProperty("machine_clicks") Long machineClicks, + @JsonProperty("machine_clicks_events") Long machineClicksEvents, + @JsonProperty("privacy_opens") Long privacyOpens, + @JsonProperty("privacy_opens_events") Long privacyOpensEvents, + @JsonProperty("privacy_clicks") Long privacyClicks, + @JsonProperty("privacy_clicks_events") Long privacyClicksEvents, + @JsonProperty("bot_opens") Long botOpens, + @JsonProperty("bot_opens_events") Long botOpensEvents, + @JsonProperty("bot_clicks") Long botClicks, + @JsonProperty("bot_clicks_events") Long botClicksEvents, + @JsonProperty("scanner_opens") Long scannerOpens, + @JsonProperty("scanner_opens_events") Long scannerOpensEvents, + @JsonProperty("scanner_clicks") Long scannerClicks, + @JsonProperty("scanner_clicks_events") Long scannerClicksEvents, + @JsonProperty("observed_opens") Long observedOpens, + @JsonProperty("observed_opens_events") Long observedOpensEvents, + @JsonProperty("observed_clicks") Long observedClicks, + @JsonProperty("observed_clicks_events") Long observedClicksEvents, + @JsonProperty("delivery_rate") Double deliveryRate, + @JsonProperty("effective_delivery_rate") Double effectiveDeliveryRate, + @JsonProperty("bounce_rate") Double bounceRate, + @JsonProperty("deferral_rate") Double deferralRate, + @JsonProperty("complaint_rate") Double complaintRate, + @JsonProperty("human_open_rate") Double humanOpenRate, + @JsonProperty("human_click_rate") Double humanClickRate, + @JsonProperty("processing_latency_p50_ms") Double processingLatencyP50Ms, + @JsonProperty("processing_latency_p95_ms") Double processingLatencyP95Ms, + @JsonProperty("processing_latency_p99_ms") Double processingLatencyP99Ms, + @JsonProperty("processing_latency_samples") Long processingLatencySamples, + @JsonProperty("delivery_latency_p50_ms") Double deliveryLatencyP50Ms, + @JsonProperty("delivery_latency_p95_ms") Double deliveryLatencyP95Ms, + @JsonProperty("delivery_latency_p99_ms") Double deliveryLatencyP99Ms, + @JsonProperty("delivery_latency_samples") Long deliveryLatencySamples, + @JsonProperty("total_latency_p50_ms") Double totalLatencyP50Ms, + @JsonProperty("total_latency_p95_ms") Double totalLatencyP95Ms, + @JsonProperty("total_latency_p99_ms") Double totalLatencyP99Ms, + @JsonProperty("total_latency_samples") Long totalLatencySamples +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsMetricValues. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.accepted = accepted; + builder.processed = processed; + builder.suppressed = suppressed; + builder.policyRejected = policyRejected; + builder.applicationFailed = applicationFailed; + builder.mtaAccepted = mtaAccepted; + builder.canceled = canceled; + builder.messages = messages; + builder.delivered = delivered; + builder.bounced = bounced; + builder.softBounced = softBounced; + builder.administrativelyBounced = administrativelyBounced; + builder.deferredRecipients = deferredRecipients; + builder.deferredEvents = deferredEvents; + builder.deliveryAttempts = deliveryAttempts; + builder.attemptedRecipients = attemptedRecipients; + builder.transportOutcomeRecipients = transportOutcomeRecipients; + builder.effectiveDelivered = effectiveDelivered; + builder.openTrackedDelivered = openTrackedDelivered; + builder.clickTrackedDelivered = clickTrackedDelivered; + builder.outOfBandBouncedRecipients = outOfBandBouncedRecipients; + builder.outOfBandBounceEvents = outOfBandBounceEvents; + builder.complained = complained; + builder.unsubscribed = unsubscribed; + builder.humanOpens = humanOpens; + builder.humanOpensEvents = humanOpensEvents; + builder.humanClicks = humanClicks; + builder.humanClicksEvents = humanClicksEvents; + builder.machineOpens = machineOpens; + builder.machineOpensEvents = machineOpensEvents; + builder.machineClicks = machineClicks; + builder.machineClicksEvents = machineClicksEvents; + builder.privacyOpens = privacyOpens; + builder.privacyOpensEvents = privacyOpensEvents; + builder.privacyClicks = privacyClicks; + builder.privacyClicksEvents = privacyClicksEvents; + builder.botOpens = botOpens; + builder.botOpensEvents = botOpensEvents; + builder.botClicks = botClicks; + builder.botClicksEvents = botClicksEvents; + builder.scannerOpens = scannerOpens; + builder.scannerOpensEvents = scannerOpensEvents; + builder.scannerClicks = scannerClicks; + builder.scannerClicksEvents = scannerClicksEvents; + builder.observedOpens = observedOpens; + builder.observedOpensEvents = observedOpensEvents; + builder.observedClicks = observedClicks; + builder.observedClicksEvents = observedClicksEvents; + builder.deliveryRate = deliveryRate; + builder.effectiveDeliveryRate = effectiveDeliveryRate; + builder.bounceRate = bounceRate; + builder.deferralRate = deferralRate; + builder.complaintRate = complaintRate; + builder.humanOpenRate = humanOpenRate; + builder.humanClickRate = humanClickRate; + builder.processingLatencyP50Ms = processingLatencyP50Ms; + builder.processingLatencyP95Ms = processingLatencyP95Ms; + builder.processingLatencyP99Ms = processingLatencyP99Ms; + builder.processingLatencySamples = processingLatencySamples; + builder.deliveryLatencyP50Ms = deliveryLatencyP50Ms; + builder.deliveryLatencyP95Ms = deliveryLatencyP95Ms; + builder.deliveryLatencyP99Ms = deliveryLatencyP99Ms; + builder.deliveryLatencySamples = deliveryLatencySamples; + builder.totalLatencyP50Ms = totalLatencyP50Ms; + builder.totalLatencyP95Ms = totalLatencyP95Ms; + builder.totalLatencyP99Ms = totalLatencyP99Ms; + builder.totalLatencySamples = totalLatencySamples; + return builder; + } + + /** Builds a {@link AnalyticsMetricValues}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long accepted; + private Long processed; + private Long suppressed; + private Long policyRejected; + private Long applicationFailed; + private Long mtaAccepted; + private Long canceled; + private Long messages; + private Long delivered; + private Long bounced; + private Long softBounced; + private Long administrativelyBounced; + private Long deferredRecipients; + private Long deferredEvents; + private Long deliveryAttempts; + private Long attemptedRecipients; + private Long transportOutcomeRecipients; + private Long effectiveDelivered; + private Long openTrackedDelivered; + private Long clickTrackedDelivered; + private Long outOfBandBouncedRecipients; + private Long outOfBandBounceEvents; + private Long complained; + private Long unsubscribed; + private Long humanOpens; + private Long humanOpensEvents; + private Long humanClicks; + private Long humanClicksEvents; + private Long machineOpens; + private Long machineOpensEvents; + private Long machineClicks; + private Long machineClicksEvents; + private Long privacyOpens; + private Long privacyOpensEvents; + private Long privacyClicks; + private Long privacyClicksEvents; + private Long botOpens; + private Long botOpensEvents; + private Long botClicks; + private Long botClicksEvents; + private Long scannerOpens; + private Long scannerOpensEvents; + private Long scannerClicks; + private Long scannerClicksEvents; + private Long observedOpens; + private Long observedOpensEvents; + private Long observedClicks; + private Long observedClicksEvents; + private Double deliveryRate; + private Double effectiveDeliveryRate; + private Double bounceRate; + private Double deferralRate; + private Double complaintRate; + private Double humanOpenRate; + private Double humanClickRate; + private Double processingLatencyP50Ms; + private Double processingLatencyP95Ms; + private Double processingLatencyP99Ms; + private Long processingLatencySamples; + private Double deliveryLatencyP50Ms; + private Double deliveryLatencyP95Ms; + private Double deliveryLatencyP99Ms; + private Long deliveryLatencySamples; + private Double totalLatencyP50Ms; + private Double totalLatencyP95Ms; + private Double totalLatencyP99Ms; + private Long totalLatencySamples; + + private Builder() { + } + + /** Sets {@code accepted}. */ + public Builder accepted(Long accepted) { + this.accepted = accepted; + return this; + } + + /** Sets {@code accepted}. */ + public Builder accepted(long accepted) { + this.accepted = accepted; + return this; + } + + /** Sets {@code processed}. */ + public Builder processed(Long processed) { + this.processed = processed; + return this; + } + + /** Sets {@code processed}. */ + public Builder processed(long processed) { + this.processed = processed; + return this; + } + + /** Sets {@code suppressed}. */ + public Builder suppressed(Long suppressed) { + this.suppressed = suppressed; + return this; + } + + /** Sets {@code suppressed}. */ + public Builder suppressed(long suppressed) { + this.suppressed = suppressed; + return this; + } + + /** Sets {@code policy_rejected}. */ + public Builder policyRejected(Long policyRejected) { + this.policyRejected = policyRejected; + return this; + } + + /** Sets {@code policy_rejected}. */ + public Builder policyRejected(long policyRejected) { + this.policyRejected = policyRejected; + return this; + } + + /** Sets {@code application_failed}. */ + public Builder applicationFailed(Long applicationFailed) { + this.applicationFailed = applicationFailed; + return this; + } + + /** Sets {@code application_failed}. */ + public Builder applicationFailed(long applicationFailed) { + this.applicationFailed = applicationFailed; + return this; + } + + /** Sets {@code mta_accepted}. */ + public Builder mtaAccepted(Long mtaAccepted) { + this.mtaAccepted = mtaAccepted; + return this; + } + + /** Sets {@code mta_accepted}. */ + public Builder mtaAccepted(long mtaAccepted) { + this.mtaAccepted = mtaAccepted; + return this; + } + + /** Sets {@code canceled}. */ + public Builder canceled(Long canceled) { + this.canceled = canceled; + return this; + } + + /** Sets {@code canceled}. */ + public Builder canceled(long canceled) { + this.canceled = canceled; + return this; + } + + /** Sets {@code messages}. */ + public Builder messages(Long messages) { + this.messages = messages; + return this; + } + + /** Sets {@code messages}. */ + public Builder messages(long messages) { + this.messages = messages; + return this; + } + + /** Sets {@code delivered}. */ + public Builder delivered(Long delivered) { + this.delivered = delivered; + return this; + } + + /** Sets {@code delivered}. */ + public Builder delivered(long delivered) { + this.delivered = delivered; + return this; + } + + /** Sets {@code bounced}. */ + public Builder bounced(Long bounced) { + this.bounced = bounced; + return this; + } + + /** Sets {@code bounced}. */ + public Builder bounced(long bounced) { + this.bounced = bounced; + return this; + } + + /** Sets {@code soft_bounced}. */ + public Builder softBounced(Long softBounced) { + this.softBounced = softBounced; + return this; + } + + /** Sets {@code soft_bounced}. */ + public Builder softBounced(long softBounced) { + this.softBounced = softBounced; + return this; + } + + /** Sets {@code administratively_bounced}. */ + public Builder administrativelyBounced(Long administrativelyBounced) { + this.administrativelyBounced = administrativelyBounced; + return this; + } + + /** Sets {@code administratively_bounced}. */ + public Builder administrativelyBounced(long administrativelyBounced) { + this.administrativelyBounced = administrativelyBounced; + return this; + } + + /** Sets {@code deferred_recipients}. */ + public Builder deferredRecipients(Long deferredRecipients) { + this.deferredRecipients = deferredRecipients; + return this; + } + + /** Sets {@code deferred_recipients}. */ + public Builder deferredRecipients(long deferredRecipients) { + this.deferredRecipients = deferredRecipients; + return this; + } + + /** Sets {@code deferred_events}. */ + public Builder deferredEvents(Long deferredEvents) { + this.deferredEvents = deferredEvents; + return this; + } + + /** Sets {@code deferred_events}. */ + public Builder deferredEvents(long deferredEvents) { + this.deferredEvents = deferredEvents; + return this; + } + + /** Sets {@code delivery_attempts}. */ + public Builder deliveryAttempts(Long deliveryAttempts) { + this.deliveryAttempts = deliveryAttempts; + return this; + } + + /** Sets {@code delivery_attempts}. */ + public Builder deliveryAttempts(long deliveryAttempts) { + this.deliveryAttempts = deliveryAttempts; + return this; + } + + /** Sets {@code attempted_recipients}. */ + public Builder attemptedRecipients(Long attemptedRecipients) { + this.attemptedRecipients = attemptedRecipients; + return this; + } + + /** Sets {@code attempted_recipients}. */ + public Builder attemptedRecipients(long attemptedRecipients) { + this.attemptedRecipients = attemptedRecipients; + return this; + } + + /** Sets {@code transport_outcome_recipients}. */ + public Builder transportOutcomeRecipients(Long transportOutcomeRecipients) { + this.transportOutcomeRecipients = transportOutcomeRecipients; + return this; + } + + /** Sets {@code transport_outcome_recipients}. */ + public Builder transportOutcomeRecipients(long transportOutcomeRecipients) { + this.transportOutcomeRecipients = transportOutcomeRecipients; + return this; + } + + /** Sets {@code effective_delivered}. */ + public Builder effectiveDelivered(Long effectiveDelivered) { + this.effectiveDelivered = effectiveDelivered; + return this; + } + + /** Sets {@code effective_delivered}. */ + public Builder effectiveDelivered(long effectiveDelivered) { + this.effectiveDelivered = effectiveDelivered; + return this; + } + + /** Sets {@code open_tracked_delivered}. */ + public Builder openTrackedDelivered(Long openTrackedDelivered) { + this.openTrackedDelivered = openTrackedDelivered; + return this; + } + + /** Sets {@code open_tracked_delivered}. */ + public Builder openTrackedDelivered(long openTrackedDelivered) { + this.openTrackedDelivered = openTrackedDelivered; + return this; + } + + /** Sets {@code click_tracked_delivered}. */ + public Builder clickTrackedDelivered(Long clickTrackedDelivered) { + this.clickTrackedDelivered = clickTrackedDelivered; + return this; + } + + /** Sets {@code click_tracked_delivered}. */ + public Builder clickTrackedDelivered(long clickTrackedDelivered) { + this.clickTrackedDelivered = clickTrackedDelivered; + return this; + } + + /** Sets {@code out_of_band_bounced_recipients}. */ + public Builder outOfBandBouncedRecipients(Long outOfBandBouncedRecipients) { + this.outOfBandBouncedRecipients = outOfBandBouncedRecipients; + return this; + } + + /** Sets {@code out_of_band_bounced_recipients}. */ + public Builder outOfBandBouncedRecipients(long outOfBandBouncedRecipients) { + this.outOfBandBouncedRecipients = outOfBandBouncedRecipients; + return this; + } + + /** Sets {@code out_of_band_bounce_events}. */ + public Builder outOfBandBounceEvents(Long outOfBandBounceEvents) { + this.outOfBandBounceEvents = outOfBandBounceEvents; + return this; + } + + /** Sets {@code out_of_band_bounce_events}. */ + public Builder outOfBandBounceEvents(long outOfBandBounceEvents) { + this.outOfBandBounceEvents = outOfBandBounceEvents; + return this; + } + + /** Sets {@code complained}. */ + public Builder complained(Long complained) { + this.complained = complained; + return this; + } + + /** Sets {@code complained}. */ + public Builder complained(long complained) { + this.complained = complained; + return this; + } + + /** Sets {@code unsubscribed}. */ + public Builder unsubscribed(Long unsubscribed) { + this.unsubscribed = unsubscribed; + return this; + } + + /** Sets {@code unsubscribed}. */ + public Builder unsubscribed(long unsubscribed) { + this.unsubscribed = unsubscribed; + return this; + } + + /** Sets {@code human_opens}. */ + public Builder humanOpens(Long humanOpens) { + this.humanOpens = humanOpens; + return this; + } + + /** Sets {@code human_opens}. */ + public Builder humanOpens(long humanOpens) { + this.humanOpens = humanOpens; + return this; + } + + /** Sets {@code human_opens_events}. */ + public Builder humanOpensEvents(Long humanOpensEvents) { + this.humanOpensEvents = humanOpensEvents; + return this; + } + + /** Sets {@code human_opens_events}. */ + public Builder humanOpensEvents(long humanOpensEvents) { + this.humanOpensEvents = humanOpensEvents; + return this; + } + + /** Sets {@code human_clicks}. */ + public Builder humanClicks(Long humanClicks) { + this.humanClicks = humanClicks; + return this; + } + + /** Sets {@code human_clicks}. */ + public Builder humanClicks(long humanClicks) { + this.humanClicks = humanClicks; + return this; + } + + /** Sets {@code human_clicks_events}. */ + public Builder humanClicksEvents(Long humanClicksEvents) { + this.humanClicksEvents = humanClicksEvents; + return this; + } + + /** Sets {@code human_clicks_events}. */ + public Builder humanClicksEvents(long humanClicksEvents) { + this.humanClicksEvents = humanClicksEvents; + return this; + } + + /** Sets {@code machine_opens}. */ + public Builder machineOpens(Long machineOpens) { + this.machineOpens = machineOpens; + return this; + } + + /** Sets {@code machine_opens}. */ + public Builder machineOpens(long machineOpens) { + this.machineOpens = machineOpens; + return this; + } + + /** Sets {@code machine_opens_events}. */ + public Builder machineOpensEvents(Long machineOpensEvents) { + this.machineOpensEvents = machineOpensEvents; + return this; + } + + /** Sets {@code machine_opens_events}. */ + public Builder machineOpensEvents(long machineOpensEvents) { + this.machineOpensEvents = machineOpensEvents; + return this; + } + + /** Sets {@code machine_clicks}. */ + public Builder machineClicks(Long machineClicks) { + this.machineClicks = machineClicks; + return this; + } + + /** Sets {@code machine_clicks}. */ + public Builder machineClicks(long machineClicks) { + this.machineClicks = machineClicks; + return this; + } + + /** Sets {@code machine_clicks_events}. */ + public Builder machineClicksEvents(Long machineClicksEvents) { + this.machineClicksEvents = machineClicksEvents; + return this; + } + + /** Sets {@code machine_clicks_events}. */ + public Builder machineClicksEvents(long machineClicksEvents) { + this.machineClicksEvents = machineClicksEvents; + return this; + } + + /** Sets {@code privacy_opens}. */ + public Builder privacyOpens(Long privacyOpens) { + this.privacyOpens = privacyOpens; + return this; + } + + /** Sets {@code privacy_opens}. */ + public Builder privacyOpens(long privacyOpens) { + this.privacyOpens = privacyOpens; + return this; + } + + /** Sets {@code privacy_opens_events}. */ + public Builder privacyOpensEvents(Long privacyOpensEvents) { + this.privacyOpensEvents = privacyOpensEvents; + return this; + } + + /** Sets {@code privacy_opens_events}. */ + public Builder privacyOpensEvents(long privacyOpensEvents) { + this.privacyOpensEvents = privacyOpensEvents; + return this; + } + + /** Sets {@code privacy_clicks}. */ + public Builder privacyClicks(Long privacyClicks) { + this.privacyClicks = privacyClicks; + return this; + } + + /** Sets {@code privacy_clicks}. */ + public Builder privacyClicks(long privacyClicks) { + this.privacyClicks = privacyClicks; + return this; + } + + /** Sets {@code privacy_clicks_events}. */ + public Builder privacyClicksEvents(Long privacyClicksEvents) { + this.privacyClicksEvents = privacyClicksEvents; + return this; + } + + /** Sets {@code privacy_clicks_events}. */ + public Builder privacyClicksEvents(long privacyClicksEvents) { + this.privacyClicksEvents = privacyClicksEvents; + return this; + } + + /** Sets {@code bot_opens}. */ + public Builder botOpens(Long botOpens) { + this.botOpens = botOpens; + return this; + } + + /** Sets {@code bot_opens}. */ + public Builder botOpens(long botOpens) { + this.botOpens = botOpens; + return this; + } + + /** Sets {@code bot_opens_events}. */ + public Builder botOpensEvents(Long botOpensEvents) { + this.botOpensEvents = botOpensEvents; + return this; + } + + /** Sets {@code bot_opens_events}. */ + public Builder botOpensEvents(long botOpensEvents) { + this.botOpensEvents = botOpensEvents; + return this; + } + + /** Sets {@code bot_clicks}. */ + public Builder botClicks(Long botClicks) { + this.botClicks = botClicks; + return this; + } + + /** Sets {@code bot_clicks}. */ + public Builder botClicks(long botClicks) { + this.botClicks = botClicks; + return this; + } + + /** Sets {@code bot_clicks_events}. */ + public Builder botClicksEvents(Long botClicksEvents) { + this.botClicksEvents = botClicksEvents; + return this; + } + + /** Sets {@code bot_clicks_events}. */ + public Builder botClicksEvents(long botClicksEvents) { + this.botClicksEvents = botClicksEvents; + return this; + } + + /** Sets {@code scanner_opens}. */ + public Builder scannerOpens(Long scannerOpens) { + this.scannerOpens = scannerOpens; + return this; + } + + /** Sets {@code scanner_opens}. */ + public Builder scannerOpens(long scannerOpens) { + this.scannerOpens = scannerOpens; + return this; + } + + /** Sets {@code scanner_opens_events}. */ + public Builder scannerOpensEvents(Long scannerOpensEvents) { + this.scannerOpensEvents = scannerOpensEvents; + return this; + } + + /** Sets {@code scanner_opens_events}. */ + public Builder scannerOpensEvents(long scannerOpensEvents) { + this.scannerOpensEvents = scannerOpensEvents; + return this; + } + + /** Sets {@code scanner_clicks}. */ + public Builder scannerClicks(Long scannerClicks) { + this.scannerClicks = scannerClicks; + return this; + } + + /** Sets {@code scanner_clicks}. */ + public Builder scannerClicks(long scannerClicks) { + this.scannerClicks = scannerClicks; + return this; + } + + /** Sets {@code scanner_clicks_events}. */ + public Builder scannerClicksEvents(Long scannerClicksEvents) { + this.scannerClicksEvents = scannerClicksEvents; + return this; + } + + /** Sets {@code scanner_clicks_events}. */ + public Builder scannerClicksEvents(long scannerClicksEvents) { + this.scannerClicksEvents = scannerClicksEvents; + return this; + } + + /** Sets {@code observed_opens}. */ + public Builder observedOpens(Long observedOpens) { + this.observedOpens = observedOpens; + return this; + } + + /** Sets {@code observed_opens}. */ + public Builder observedOpens(long observedOpens) { + this.observedOpens = observedOpens; + return this; + } + + /** Sets {@code observed_opens_events}. */ + public Builder observedOpensEvents(Long observedOpensEvents) { + this.observedOpensEvents = observedOpensEvents; + return this; + } + + /** Sets {@code observed_opens_events}. */ + public Builder observedOpensEvents(long observedOpensEvents) { + this.observedOpensEvents = observedOpensEvents; + return this; + } + + /** Sets {@code observed_clicks}. */ + public Builder observedClicks(Long observedClicks) { + this.observedClicks = observedClicks; + return this; + } + + /** Sets {@code observed_clicks}. */ + public Builder observedClicks(long observedClicks) { + this.observedClicks = observedClicks; + return this; + } + + /** Sets {@code observed_clicks_events}. */ + public Builder observedClicksEvents(Long observedClicksEvents) { + this.observedClicksEvents = observedClicksEvents; + return this; + } + + /** Sets {@code observed_clicks_events}. */ + public Builder observedClicksEvents(long observedClicksEvents) { + this.observedClicksEvents = observedClicksEvents; + return this; + } + + /** Sets {@code delivery_rate}. */ + public Builder deliveryRate(Double deliveryRate) { + this.deliveryRate = deliveryRate; + return this; + } + + /** Sets {@code delivery_rate}. */ + public Builder deliveryRate(double deliveryRate) { + this.deliveryRate = deliveryRate; + return this; + } + + /** Sets {@code effective_delivery_rate}. */ + public Builder effectiveDeliveryRate(Double effectiveDeliveryRate) { + this.effectiveDeliveryRate = effectiveDeliveryRate; + return this; + } + + /** Sets {@code effective_delivery_rate}. */ + public Builder effectiveDeliveryRate(double effectiveDeliveryRate) { + this.effectiveDeliveryRate = effectiveDeliveryRate; + return this; + } + + /** Sets {@code bounce_rate}. */ + public Builder bounceRate(Double bounceRate) { + this.bounceRate = bounceRate; + return this; + } + + /** Sets {@code bounce_rate}. */ + public Builder bounceRate(double bounceRate) { + this.bounceRate = bounceRate; + return this; + } + + /** Sets {@code deferral_rate}. */ + public Builder deferralRate(Double deferralRate) { + this.deferralRate = deferralRate; + return this; + } + + /** Sets {@code deferral_rate}. */ + public Builder deferralRate(double deferralRate) { + this.deferralRate = deferralRate; + return this; + } + + /** Sets {@code complaint_rate}. */ + public Builder complaintRate(Double complaintRate) { + this.complaintRate = complaintRate; + return this; + } + + /** Sets {@code complaint_rate}. */ + public Builder complaintRate(double complaintRate) { + this.complaintRate = complaintRate; + return this; + } + + /** Sets {@code human_open_rate}. */ + public Builder humanOpenRate(Double humanOpenRate) { + this.humanOpenRate = humanOpenRate; + return this; + } + + /** Sets {@code human_open_rate}. */ + public Builder humanOpenRate(double humanOpenRate) { + this.humanOpenRate = humanOpenRate; + return this; + } + + /** Sets {@code human_click_rate}. */ + public Builder humanClickRate(Double humanClickRate) { + this.humanClickRate = humanClickRate; + return this; + } + + /** Sets {@code human_click_rate}. */ + public Builder humanClickRate(double humanClickRate) { + this.humanClickRate = humanClickRate; + return this; + } + + /** Sets {@code processing_latency_p50_ms}. */ + public Builder processingLatencyP50Ms(Double processingLatencyP50Ms) { + this.processingLatencyP50Ms = processingLatencyP50Ms; + return this; + } + + /** Sets {@code processing_latency_p50_ms}. */ + public Builder processingLatencyP50Ms(double processingLatencyP50Ms) { + this.processingLatencyP50Ms = processingLatencyP50Ms; + return this; + } + + /** Sets {@code processing_latency_p95_ms}. */ + public Builder processingLatencyP95Ms(Double processingLatencyP95Ms) { + this.processingLatencyP95Ms = processingLatencyP95Ms; + return this; + } + + /** Sets {@code processing_latency_p95_ms}. */ + public Builder processingLatencyP95Ms(double processingLatencyP95Ms) { + this.processingLatencyP95Ms = processingLatencyP95Ms; + return this; + } + + /** Sets {@code processing_latency_p99_ms}. */ + public Builder processingLatencyP99Ms(Double processingLatencyP99Ms) { + this.processingLatencyP99Ms = processingLatencyP99Ms; + return this; + } + + /** Sets {@code processing_latency_p99_ms}. */ + public Builder processingLatencyP99Ms(double processingLatencyP99Ms) { + this.processingLatencyP99Ms = processingLatencyP99Ms; + return this; + } + + /** Sets {@code processing_latency_samples}. */ + public Builder processingLatencySamples(Long processingLatencySamples) { + this.processingLatencySamples = processingLatencySamples; + return this; + } + + /** Sets {@code processing_latency_samples}. */ + public Builder processingLatencySamples(long processingLatencySamples) { + this.processingLatencySamples = processingLatencySamples; + return this; + } + + /** Sets {@code delivery_latency_p50_ms}. */ + public Builder deliveryLatencyP50Ms(Double deliveryLatencyP50Ms) { + this.deliveryLatencyP50Ms = deliveryLatencyP50Ms; + return this; + } + + /** Sets {@code delivery_latency_p50_ms}. */ + public Builder deliveryLatencyP50Ms(double deliveryLatencyP50Ms) { + this.deliveryLatencyP50Ms = deliveryLatencyP50Ms; + return this; + } + + /** Sets {@code delivery_latency_p95_ms}. */ + public Builder deliveryLatencyP95Ms(Double deliveryLatencyP95Ms) { + this.deliveryLatencyP95Ms = deliveryLatencyP95Ms; + return this; + } + + /** Sets {@code delivery_latency_p95_ms}. */ + public Builder deliveryLatencyP95Ms(double deliveryLatencyP95Ms) { + this.deliveryLatencyP95Ms = deliveryLatencyP95Ms; + return this; + } + + /** Sets {@code delivery_latency_p99_ms}. */ + public Builder deliveryLatencyP99Ms(Double deliveryLatencyP99Ms) { + this.deliveryLatencyP99Ms = deliveryLatencyP99Ms; + return this; + } + + /** Sets {@code delivery_latency_p99_ms}. */ + public Builder deliveryLatencyP99Ms(double deliveryLatencyP99Ms) { + this.deliveryLatencyP99Ms = deliveryLatencyP99Ms; + return this; + } + + /** Sets {@code delivery_latency_samples}. */ + public Builder deliveryLatencySamples(Long deliveryLatencySamples) { + this.deliveryLatencySamples = deliveryLatencySamples; + return this; + } + + /** Sets {@code delivery_latency_samples}. */ + public Builder deliveryLatencySamples(long deliveryLatencySamples) { + this.deliveryLatencySamples = deliveryLatencySamples; + return this; + } + + /** Sets {@code total_latency_p50_ms}. */ + public Builder totalLatencyP50Ms(Double totalLatencyP50Ms) { + this.totalLatencyP50Ms = totalLatencyP50Ms; + return this; + } + + /** Sets {@code total_latency_p50_ms}. */ + public Builder totalLatencyP50Ms(double totalLatencyP50Ms) { + this.totalLatencyP50Ms = totalLatencyP50Ms; + return this; + } + + /** Sets {@code total_latency_p95_ms}. */ + public Builder totalLatencyP95Ms(Double totalLatencyP95Ms) { + this.totalLatencyP95Ms = totalLatencyP95Ms; + return this; + } + + /** Sets {@code total_latency_p95_ms}. */ + public Builder totalLatencyP95Ms(double totalLatencyP95Ms) { + this.totalLatencyP95Ms = totalLatencyP95Ms; + return this; + } + + /** Sets {@code total_latency_p99_ms}. */ + public Builder totalLatencyP99Ms(Double totalLatencyP99Ms) { + this.totalLatencyP99Ms = totalLatencyP99Ms; + return this; + } + + /** Sets {@code total_latency_p99_ms}. */ + public Builder totalLatencyP99Ms(double totalLatencyP99Ms) { + this.totalLatencyP99Ms = totalLatencyP99Ms; + return this; + } + + /** Sets {@code total_latency_samples}. */ + public Builder totalLatencySamples(Long totalLatencySamples) { + this.totalLatencySamples = totalLatencySamples; + return this; + } + + /** Sets {@code total_latency_samples}. */ + public Builder totalLatencySamples(long totalLatencySamples) { + this.totalLatencySamples = totalLatencySamples; + return this; + } + + /** Returns the {@link AnalyticsMetricValues}. */ + public AnalyticsMetricValues build() { + return new AnalyticsMetricValues(accepted, processed, suppressed, policyRejected, applicationFailed, mtaAccepted, canceled, messages, delivered, bounced, softBounced, administrativelyBounced, deferredRecipients, deferredEvents, deliveryAttempts, attemptedRecipients, transportOutcomeRecipients, effectiveDelivered, openTrackedDelivered, clickTrackedDelivered, outOfBandBouncedRecipients, outOfBandBounceEvents, complained, unsubscribed, humanOpens, humanOpensEvents, humanClicks, humanClicksEvents, machineOpens, machineOpensEvents, machineClicks, machineClicksEvents, privacyOpens, privacyOpensEvents, privacyClicks, privacyClicksEvents, botOpens, botOpensEvents, botClicks, botClicksEvents, scannerOpens, scannerOpensEvents, scannerClicks, scannerClicksEvents, observedOpens, observedOpensEvents, observedClicks, observedClicksEvents, deliveryRate, effectiveDeliveryRate, bounceRate, deferralRate, complaintRate, humanOpenRate, humanClickRate, processingLatencyP50Ms, processingLatencyP95Ms, processingLatencyP99Ms, processingLatencySamples, deliveryLatencyP50Ms, deliveryLatencyP95Ms, deliveryLatencyP99Ms, deliveryLatencySamples, totalLatencyP50Ms, totalLatencyP95Ms, totalLatencyP99Ms, totalLatencySamples); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsPagination.java b/src/main/java/co/lettermint/types/AnalyticsPagination.java new file mode 100644 index 0000000..ca7911a --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsPagination.java @@ -0,0 +1,96 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Breakdown pagination. + * + * @param totalGroups Always present. + * @param returnedGroups Always present. + * @param nextCursor Always present; may be null. + * @param truncated Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsPagination( + @JsonProperty("total_groups") Long totalGroups, + @JsonProperty("returned_groups") Long returnedGroups, + @JsonProperty("next_cursor") String nextCursor, + @JsonProperty("truncated") Boolean truncated +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsPagination. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.totalGroups = totalGroups; + builder.returnedGroups = returnedGroups; + builder.nextCursor = nextCursor; + builder.truncated = truncated; + return builder; + } + + /** Builds a {@link AnalyticsPagination}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long totalGroups; + private Long returnedGroups; + private String nextCursor; + private Boolean truncated; + + private Builder() { + } + + /** Sets {@code total_groups}. */ + public Builder totalGroups(Long totalGroups) { + this.totalGroups = totalGroups; + return this; + } + + /** Sets {@code total_groups}. */ + public Builder totalGroups(long totalGroups) { + this.totalGroups = totalGroups; + return this; + } + + /** Sets {@code returned_groups}. */ + public Builder returnedGroups(Long returnedGroups) { + this.returnedGroups = returnedGroups; + return this; + } + + /** Sets {@code returned_groups}. */ + public Builder returnedGroups(long returnedGroups) { + this.returnedGroups = returnedGroups; + return this; + } + + /** Sets {@code next_cursor}. */ + public Builder nextCursor(String nextCursor) { + this.nextCursor = nextCursor; + return this; + } + + /** Sets {@code truncated}. */ + public Builder truncated(Boolean truncated) { + this.truncated = truncated; + return this; + } + + /** Returns the {@link AnalyticsPagination}. */ + public AnalyticsPagination build() { + return new AnalyticsPagination(totalGroups, returnedGroups, nextCursor, truncated); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsQuery.java b/src/main/java/co/lettermint/types/AnalyticsQuery.java new file mode 100644 index 0000000..9df9de1 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsQuery.java @@ -0,0 +1,189 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * An analytics query. + * + * @param metrics Every count is attributed to the time its event occurred, so a message accepted in one bucket can be delivered in the next. Delivery outcomes happen once per recipient, so their event counts equal recipient counts. messages counts accepted messages; mta_accepted and attempted_recipients count recipients the MTA received. Under provider, infrastructure and diagnosis dimensions, sent/attempted count delivery attempts: mta_accepted and attempted_recipients equal delivery_attempts when a query groups or filters by provider_family, provider_subtype, dedicated_ip, dedicated_pool_id, infrastructure_state or an SMTP diagnosis dimension, because the MTA assigns those values at the delivery attempt; the other lifecycle metrics return null there, and a breakdown by those dimensions omits the unknown group. deferred_recipients counts recipients delayed on the first attempt; deferred_events counts every deferral. delivery_attempts counts delivered, deferred and in-band bounced attempts. transport_outcome_recipients = delivered + bounced + soft_bounced. effective_delivered = delivered minus out-of-band bounces in the same period and can be negative for a single bucket or group. Engagement counts per class are unique per recipient, counted when the first qualifying open or click occurred; _events variants count every observation. Rates are fractions; zero denominators return null, and event-time rates can exceed 1. Latency percentiles are milliseconds read from log-scale histograms (error below 15 percent); _samples returns the sample count. Personal message dimensions support daily buckets over the message retention period. delivery_rate = delivered / transport_outcome_recipients. effective_delivery_rate = effective_delivered / transport_outcome_recipients. bounce_rate = bounced / transport_outcome_recipients. deferral_rate = deferred_events / delivery_attempts. complaint_rate = complained / delivered. human_open_rate = human_opens / open_tracked_delivered. human_click_rate = human_clicks / click_tracked_delivered. Required. + * @param from Inclusive calendar date or RFC 3339 instant. Default: 30 calendar days including today. Instants are aligned outward to whole UTC hours, or whole UTC days when from_address or subject is grouped or filtered; meta.from, meta.to, meta.effective_to and meta.alignment report the exact window used. Optional: null omits it. + * @param to Inclusive calendar date or exclusive RFC 3339 instant. Maximum window: 90 days. Instants are aligned outward to whole UTC hours, or whole UTC days when from_address or subject is grouped or filtered; meta.from, meta.to, meta.effective_to and meta.alignment report the exact window used. Optional: null omits it. + * @param timezone IANA time zone. Default: UTC. Optional: null omits it. + * @param include Result sections. Default: summary only. breakdown requires group_by, and group_by requires breakdown. Optional: null omits it. + * @param groupBy Up to three grouping dimensions for breakdown rows. Requires breakdown in include. Default: no grouping. Optional: null omits it. + * @param filters Dimension filters combined with AND. Default: no filters. Each metric must support every filter dimension. Optional: null omits it. + * @param interval Time-series bucket size. Default: day. Optional: null omits it. + * @param compare Compares with the preceding period of the same duration. Omit for no comparison. Optional: null omits it. + * @param includeTrend Includes trends for breakdown rows. Requires breakdown and group_by. Default: false. Optional: null omits it. + * @param sort Optional breakdown sort. Omit to use the default row order. Optional: null omits it. + * @param limit Maximum breakdown rows per page. Default: 50; maximum: 200. Optional: null omits it. + * @param cursor Repeat the same query with this cursor. It expires within 60 seconds. Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsQuery( + @JsonProperty("metrics") List metrics, + @JsonProperty("from") String from, + @JsonProperty("to") String to, + @JsonProperty("timezone") String timezone, + @JsonProperty("include") List include, + @JsonProperty("group_by") List groupBy, + @JsonProperty("filters") List filters, + @JsonProperty("interval") AnalyticsInterval interval, + @JsonProperty("compare") AnalyticsComparison compare, + @JsonProperty("include_trend") Boolean includeTrend, + @JsonProperty("sort") AnalyticsSort sort, + @JsonProperty("limit") Long limit, + @JsonProperty("cursor") String cursor +) { + /** Copies lists and maps into unmodifiable collections. */ + public AnalyticsQuery { + metrics = Copies.list(metrics); + include = Copies.list(include); + groupBy = Copies.list(groupBy); + filters = Copies.list(filters); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.metrics = metrics; + builder.from = from; + builder.to = to; + builder.timezone = timezone; + builder.include = include; + builder.groupBy = groupBy; + builder.filters = filters; + builder.interval = interval; + builder.compare = compare; + builder.includeTrend = includeTrend; + builder.sort = sort; + builder.limit = limit; + builder.cursor = cursor; + return builder; + } + + /** Builds a {@link AnalyticsQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List metrics; + private String from; + private String to; + private String timezone; + private List include; + private List groupBy; + private List filters; + private AnalyticsInterval interval; + private AnalyticsComparison compare; + private Boolean includeTrend; + private AnalyticsSort sort; + private Long limit; + private String cursor; + + private Builder() { + } + + /** Sets {@code metrics}. */ + public Builder metrics(List metrics) { + this.metrics = metrics; + return this; + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(String to) { + this.to = to; + return this; + } + + /** Sets {@code timezone}. */ + public Builder timezone(String timezone) { + this.timezone = timezone; + return this; + } + + /** Sets {@code include}. */ + public Builder include(List include) { + this.include = include; + return this; + } + + /** Sets {@code group_by}. */ + public Builder groupBy(List groupBy) { + this.groupBy = groupBy; + return this; + } + + /** Sets {@code filters}. */ + public Builder filters(List filters) { + this.filters = filters; + return this; + } + + /** Sets {@code interval}. */ + public Builder interval(AnalyticsInterval interval) { + this.interval = interval; + return this; + } + + /** Sets {@code compare}. */ + public Builder compare(AnalyticsComparison compare) { + this.compare = compare; + return this; + } + + /** Sets {@code include_trend}. */ + public Builder includeTrend(Boolean includeTrend) { + this.includeTrend = includeTrend; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(AnalyticsSort sort) { + this.sort = sort; + return this; + } + + /** Sets {@code limit}. */ + public Builder limit(Long limit) { + this.limit = limit; + return this; + } + + /** Sets {@code limit}. */ + public Builder limit(long limit) { + this.limit = limit; + return this; + } + + /** Sets {@code cursor}. */ + public Builder cursor(String cursor) { + this.cursor = cursor; + return this; + } + + /** Returns the {@link AnalyticsQuery}. */ + public AnalyticsQuery build() { + return new AnalyticsQuery(metrics, from, to, timezone, include, groupBy, filters, interval, compare, includeTrend, sort, limit, cursor); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsRateBase.java b/src/main/java/co/lettermint/types/AnalyticsRateBase.java new file mode 100644 index 0000000..09e8e5b --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsRateBase.java @@ -0,0 +1,76 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Numerator and denominator of a rate metric. + * + * @param numerator Always present; may be null. + * @param denominator Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsRateBase( + @JsonProperty("numerator") Long numerator, + @JsonProperty("denominator") Long denominator +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsRateBase. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.numerator = numerator; + builder.denominator = denominator; + return builder; + } + + /** Builds a {@link AnalyticsRateBase}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long numerator; + private Long denominator; + + private Builder() { + } + + /** Sets {@code numerator}. */ + public Builder numerator(Long numerator) { + this.numerator = numerator; + return this; + } + + /** Sets {@code numerator}. */ + public Builder numerator(long numerator) { + this.numerator = numerator; + return this; + } + + /** Sets {@code denominator}. */ + public Builder denominator(Long denominator) { + this.denominator = denominator; + return this; + } + + /** Sets {@code denominator}. */ + public Builder denominator(long denominator) { + this.denominator = denominator; + return this; + } + + /** Returns the {@link AnalyticsRateBase}. */ + public AnalyticsRateBase build() { + return new AnalyticsRateBase(numerator, denominator); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsRateBases.java b/src/main/java/co/lettermint/types/AnalyticsRateBases.java new file mode 100644 index 0000000..84ae42d --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsRateBases.java @@ -0,0 +1,114 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Numerators and denominators of the selected rate metrics. + * + * @param deliveryRate Optional: null when absent. + * @param effectiveDeliveryRate Optional: null when absent. + * @param bounceRate Optional: null when absent. + * @param deferralRate Optional: null when absent. + * @param complaintRate Optional: null when absent. + * @param humanOpenRate Optional: null when absent. + * @param humanClickRate Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsRateBases( + @JsonProperty("delivery_rate") AnalyticsRateBase deliveryRate, + @JsonProperty("effective_delivery_rate") AnalyticsRateBase effectiveDeliveryRate, + @JsonProperty("bounce_rate") AnalyticsRateBase bounceRate, + @JsonProperty("deferral_rate") AnalyticsRateBase deferralRate, + @JsonProperty("complaint_rate") AnalyticsRateBase complaintRate, + @JsonProperty("human_open_rate") AnalyticsRateBase humanOpenRate, + @JsonProperty("human_click_rate") AnalyticsRateBase humanClickRate +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsRateBases. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.deliveryRate = deliveryRate; + builder.effectiveDeliveryRate = effectiveDeliveryRate; + builder.bounceRate = bounceRate; + builder.deferralRate = deferralRate; + builder.complaintRate = complaintRate; + builder.humanOpenRate = humanOpenRate; + builder.humanClickRate = humanClickRate; + return builder; + } + + /** Builds a {@link AnalyticsRateBases}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsRateBase deliveryRate; + private AnalyticsRateBase effectiveDeliveryRate; + private AnalyticsRateBase bounceRate; + private AnalyticsRateBase deferralRate; + private AnalyticsRateBase complaintRate; + private AnalyticsRateBase humanOpenRate; + private AnalyticsRateBase humanClickRate; + + private Builder() { + } + + /** Sets {@code delivery_rate}. */ + public Builder deliveryRate(AnalyticsRateBase deliveryRate) { + this.deliveryRate = deliveryRate; + return this; + } + + /** Sets {@code effective_delivery_rate}. */ + public Builder effectiveDeliveryRate(AnalyticsRateBase effectiveDeliveryRate) { + this.effectiveDeliveryRate = effectiveDeliveryRate; + return this; + } + + /** Sets {@code bounce_rate}. */ + public Builder bounceRate(AnalyticsRateBase bounceRate) { + this.bounceRate = bounceRate; + return this; + } + + /** Sets {@code deferral_rate}. */ + public Builder deferralRate(AnalyticsRateBase deferralRate) { + this.deferralRate = deferralRate; + return this; + } + + /** Sets {@code complaint_rate}. */ + public Builder complaintRate(AnalyticsRateBase complaintRate) { + this.complaintRate = complaintRate; + return this; + } + + /** Sets {@code human_open_rate}. */ + public Builder humanOpenRate(AnalyticsRateBase humanOpenRate) { + this.humanOpenRate = humanOpenRate; + return this; + } + + /** Sets {@code human_click_rate}. */ + public Builder humanClickRate(AnalyticsRateBase humanClickRate) { + this.humanClickRate = humanClickRate; + return this; + } + + /** Returns the {@link AnalyticsRateBases}. */ + public AnalyticsRateBases build() { + return new AnalyticsRateBases(deliveryRate, effectiveDeliveryRate, bounceRate, deferralRate, complaintRate, humanOpenRate, humanClickRate); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsResponse.java b/src/main/java/co/lettermint/types/AnalyticsResponse.java new file mode 100644 index 0000000..bf87962 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsResponse.java @@ -0,0 +1,74 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Analytics results with their window metadata and pagination. + * + * @param data Always present. + * @param meta Always present. + * @param pagination Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsResponse( + @JsonProperty("data") AnalyticsResults data, + @JsonProperty("meta") AnalyticsMeta meta, + @JsonProperty("pagination") AnalyticsPagination pagination +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.meta = meta; + builder.pagination = pagination; + return builder; + } + + /** Builds a {@link AnalyticsResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsResults data; + private AnalyticsMeta meta; + private AnalyticsPagination pagination; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(AnalyticsResults data) { + this.data = data; + return this; + } + + /** Sets {@code meta}. */ + public Builder meta(AnalyticsMeta meta) { + this.meta = meta; + return this; + } + + /** Sets {@code pagination}. */ + public Builder pagination(AnalyticsPagination pagination) { + this.pagination = pagination; + return this; + } + + /** Returns the {@link AnalyticsResponse}. */ + public AnalyticsResponse build() { + return new AnalyticsResponse(data, meta, pagination); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsResults.java b/src/main/java/co/lettermint/types/AnalyticsResults.java new file mode 100644 index 0000000..130c3fd --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsResults.java @@ -0,0 +1,81 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * The selected result sections. + * + * @param summary Optional: null when absent. + * @param timeSeries Optional: null when absent. + * @param breakdown Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsResults( + @JsonProperty("summary") AnalyticsSummary summary, + @JsonProperty("time_series") List timeSeries, + @JsonProperty("breakdown") List breakdown +) { + /** Copies lists and maps into unmodifiable collections. */ + public AnalyticsResults { + timeSeries = Copies.list(timeSeries); + breakdown = Copies.list(breakdown); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsResults. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.summary = summary; + builder.timeSeries = timeSeries; + builder.breakdown = breakdown; + return builder; + } + + /** Builds a {@link AnalyticsResults}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsSummary summary; + private List timeSeries; + private List breakdown; + + private Builder() { + } + + /** Sets {@code summary}. */ + public Builder summary(AnalyticsSummary summary) { + this.summary = summary; + return this; + } + + /** Sets {@code time_series}. */ + public Builder timeSeries(List timeSeries) { + this.timeSeries = timeSeries; + return this; + } + + /** Sets {@code breakdown}. */ + public Builder breakdown(List breakdown) { + this.breakdown = breakdown; + return this; + } + + /** Returns the {@link AnalyticsResults}. */ + public AnalyticsResults build() { + return new AnalyticsResults(summary, timeSeries, breakdown); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsSection.java b/src/main/java/co/lettermint/types/AnalyticsSection.java new file mode 100644 index 0000000..c35b8e8 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsSection.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * A result section. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsSection { + /** {@code "summary"} */ + public static final AnalyticsSection SUMMARY = new AnalyticsSection("summary"); + + /** {@code "time_series"} */ + public static final AnalyticsSection TIME_SERIES = new AnalyticsSection("time_series"); + + /** {@code "breakdown"} */ + public static final AnalyticsSection BREAKDOWN = new AnalyticsSection("breakdown"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(SUMMARY.value, SUMMARY); + known.put(TIME_SERIES.value, TIME_SERIES); + known.put(BREAKDOWN.value, BREAKDOWN); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsSection(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsSection of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsSection known = KNOWN.get(value); + return known != null ? known : new AnalyticsSection(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsSection that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsSort.java b/src/main/java/co/lettermint/types/AnalyticsSort.java new file mode 100644 index 0000000..f4231f0 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsSort.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A breakdown sort order. + * + * @param metric Metric used to sort breakdown rows. Must also be selected in metrics. Required. + * @param direction Ascending or descending order for the selected sort metric. Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsSort( + @JsonProperty("metric") AnalyticsMetric metric, + @JsonProperty("direction") AnalyticsSortDirection direction +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsSort. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.metric = metric; + builder.direction = direction; + return builder; + } + + /** Builds a {@link AnalyticsSort}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsMetric metric; + private AnalyticsSortDirection direction; + + private Builder() { + } + + /** Sets {@code metric}. */ + public Builder metric(AnalyticsMetric metric) { + this.metric = metric; + return this; + } + + /** Sets {@code direction}. */ + public Builder direction(AnalyticsSortDirection direction) { + this.direction = direction; + return this; + } + + /** Returns the {@link AnalyticsSort}. */ + public AnalyticsSort build() { + return new AnalyticsSort(metric, direction); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsSortDirection.java b/src/main/java/co/lettermint/types/AnalyticsSortDirection.java new file mode 100644 index 0000000..ed53107 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsSortDirection.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Ascending or descending order for the selected sort metric. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class AnalyticsSortDirection { + /** {@code "asc"} */ + public static final AnalyticsSortDirection ASC = new AnalyticsSortDirection("asc"); + + /** {@code "desc"} */ + public static final AnalyticsSortDirection DESC = new AnalyticsSortDirection("desc"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(ASC.value, ASC); + known.put(DESC.value, DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AnalyticsSortDirection(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AnalyticsSortDirection of(String value) { + Objects.requireNonNull(value, "value"); + AnalyticsSortDirection known = KNOWN.get(value); + return known != null ? known : new AnalyticsSortDirection(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AnalyticsSortDirection that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsSummary.java b/src/main/java/co/lettermint/types/AnalyticsSummary.java new file mode 100644 index 0000000..de7b030 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsSummary.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; + +/** + * Metric values for the whole window. + * + * @param metrics Always present. + * @param rateBases Always present. + * @param previous Optional: null when absent. + * @param change Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsSummary( + @JsonProperty("metrics") AnalyticsMetricValues metrics, + @JsonProperty("rate_bases") AnalyticsRateBases rateBases, + @JsonProperty("previous") AnalyticsComparisonValues previous, + @JsonProperty("change") Map change +) { + /** Copies lists and maps into unmodifiable collections. */ + public AnalyticsSummary { + change = Copies.map(change); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsSummary. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.metrics = metrics; + builder.rateBases = rateBases; + builder.previous = previous; + builder.change = change; + return builder; + } + + /** Builds a {@link AnalyticsSummary}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsMetricValues metrics; + private AnalyticsRateBases rateBases; + private AnalyticsComparisonValues previous; + private Map change; + + private Builder() { + } + + /** Sets {@code metrics}. */ + public Builder metrics(AnalyticsMetricValues metrics) { + this.metrics = metrics; + return this; + } + + /** Sets {@code rate_bases}. */ + public Builder rateBases(AnalyticsRateBases rateBases) { + this.rateBases = rateBases; + return this; + } + + /** Sets {@code previous}. */ + public Builder previous(AnalyticsComparisonValues previous) { + this.previous = previous; + return this; + } + + /** Sets {@code change}. */ + public Builder change(Map change) { + this.change = change; + return this; + } + + /** Returns the {@link AnalyticsSummary}. */ + public AnalyticsSummary build() { + return new AnalyticsSummary(metrics, rateBases, previous, change); + } + } +} diff --git a/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java b/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java new file mode 100644 index 0000000..1673246 --- /dev/null +++ b/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java @@ -0,0 +1,130 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.Map; + +/** + * Metric values for one time-series bucket. + * + * @param metrics Always present. + * @param rateBases Always present. + * @param previous Optional: null when absent. + * @param change Optional: null when absent. + * @param from Always present. + * @param to Always present. + * @param available Always present. + * @param partial Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record AnalyticsTimeSeriesPoint( + @JsonProperty("metrics") AnalyticsMetricValues metrics, + @JsonProperty("rate_bases") AnalyticsRateBases rateBases, + @JsonProperty("previous") AnalyticsComparisonValues previous, + @JsonProperty("change") Map change, + @JsonProperty("from") String from, + @JsonProperty("to") String to, + @JsonProperty("available") Boolean available, + @JsonProperty("partial") Boolean partial +) { + /** Copies lists and maps into unmodifiable collections. */ + public AnalyticsTimeSeriesPoint { + change = Copies.map(change); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this AnalyticsTimeSeriesPoint. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.metrics = metrics; + builder.rateBases = rateBases; + builder.previous = previous; + builder.change = change; + builder.from = from; + builder.to = to; + builder.available = available; + builder.partial = partial; + return builder; + } + + /** Builds a {@link AnalyticsTimeSeriesPoint}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private AnalyticsMetricValues metrics; + private AnalyticsRateBases rateBases; + private AnalyticsComparisonValues previous; + private Map change; + private String from; + private String to; + private Boolean available; + private Boolean partial; + + private Builder() { + } + + /** Sets {@code metrics}. */ + public Builder metrics(AnalyticsMetricValues metrics) { + this.metrics = metrics; + return this; + } + + /** Sets {@code rate_bases}. */ + public Builder rateBases(AnalyticsRateBases rateBases) { + this.rateBases = rateBases; + return this; + } + + /** Sets {@code previous}. */ + public Builder previous(AnalyticsComparisonValues previous) { + this.previous = previous; + return this; + } + + /** Sets {@code change}. */ + public Builder change(Map change) { + this.change = change; + return this; + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(String to) { + this.to = to; + return this; + } + + /** Sets {@code available}. */ + public Builder available(Boolean available) { + this.available = available; + return this; + } + + /** Sets {@code partial}. */ + public Builder partial(Boolean partial) { + this.partial = partial; + return this; + } + + /** Returns the {@link AnalyticsTimeSeriesPoint}. */ + public AnalyticsTimeSeriesPoint build() { + return new AnalyticsTimeSeriesPoint(metrics, rateBases, previous, change, from, to, available, partial); + } + } +} diff --git a/src/main/java/co/lettermint/types/ApiError.java b/src/main/java/co/lettermint/types/ApiError.java new file mode 100644 index 0000000..d2656d0 --- /dev/null +++ b/src/main/java/co/lettermint/types/ApiError.java @@ -0,0 +1,54 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Structured API error. + * + * @param error Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ApiError( + @JsonProperty("error") ApiErrorDetail error +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ApiError. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.error = error; + return builder; + } + + /** Builds a {@link ApiError}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ApiErrorDetail error; + + private Builder() { + } + + /** Sets {@code error}. */ + public Builder error(ApiErrorDetail error) { + this.error = error; + return this; + } + + /** Returns the {@link ApiError}. */ + public ApiError build() { + return new ApiError(error); + } + } +} diff --git a/src/main/java/co/lettermint/types/ApiErrorDetail.java b/src/main/java/co/lettermint/types/ApiErrorDetail.java new file mode 100644 index 0000000..6bb3549 --- /dev/null +++ b/src/main/java/co/lettermint/types/ApiErrorDetail.java @@ -0,0 +1,72 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param code Machine-readable error code, for example RESOURCE_NOT_FOUND. Always present. + * @param message Human-readable error message. Always present. + * @param details Additional context. Its shape depends on the error code. Optional and nullable: null when absent or null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ApiErrorDetail( + @JsonProperty("code") String code, + @JsonProperty("message") String message, + @JsonProperty("details") Object details +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ApiErrorDetail. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.code = code; + builder.message = message; + builder.details = details; + return builder; + } + + /** Builds a {@link ApiErrorDetail}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String code; + private String message; + private Object details; + + private Builder() { + } + + /** Sets {@code code}. */ + public Builder code(String code) { + this.code = code; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code details}. */ + public Builder details(Object details) { + this.details = details; + return this; + } + + /** Returns the {@link ApiErrorDetail}. */ + public ApiErrorDetail build() { + return new ApiErrorDetail(code, message, details); + } + } +} diff --git a/src/main/java/co/lettermint/types/AttachmentDelivery.java b/src/main/java/co/lettermint/types/AttachmentDelivery.java new file mode 100644 index 0000000..447e801 --- /dev/null +++ b/src/main/java/co/lettermint/types/AttachmentDelivery.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class AttachmentDelivery { + /** {@code "inline"} */ + public static final AttachmentDelivery INLINE = new AttachmentDelivery("inline"); + + /** {@code "url"} */ + public static final AttachmentDelivery URL = new AttachmentDelivery("url"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(INLINE.value, INLINE); + known.put(URL.value, URL); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private AttachmentDelivery(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static AttachmentDelivery of(String value) { + Objects.requireNonNull(value, "value"); + AttachmentDelivery known = KNOWN.get(value); + return known != null ? known : new AttachmentDelivery(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof AttachmentDelivery that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/BlockedFileTypes.java b/src/main/java/co/lettermint/types/BlockedFileTypes.java new file mode 100644 index 0000000..1f8459c --- /dev/null +++ b/src/main/java/co/lettermint/types/BlockedFileTypes.java @@ -0,0 +1,71 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * File types that cannot be sent as email attachments. + * + * @param extensions Blocked file extensions, without the leading dot. Always present. + * @param mimeTypes Blocked MIME types. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record BlockedFileTypes( + @JsonProperty("extensions") List extensions, + @JsonProperty("mime_types") List mimeTypes +) { + /** Copies lists and maps into unmodifiable collections. */ + public BlockedFileTypes { + extensions = Copies.list(extensions); + mimeTypes = Copies.list(mimeTypes); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this BlockedFileTypes. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.extensions = extensions; + builder.mimeTypes = mimeTypes; + return builder; + } + + /** Builds a {@link BlockedFileTypes}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List extensions; + private List mimeTypes; + + private Builder() { + } + + /** Sets {@code extensions}. */ + public Builder extensions(List extensions) { + this.extensions = extensions; + return this; + } + + /** Sets {@code mime_types}. */ + public Builder mimeTypes(List mimeTypes) { + this.mimeTypes = mimeTypes; + return this; + } + + /** Returns the {@link BlockedFileTypes}. */ + public BlockedFileTypes build() { + return new BlockedFileTypes(extensions, mimeTypes); + } + } +} diff --git a/src/main/java/co/lettermint/types/BuiltInTeamRole.java b/src/main/java/co/lettermint/types/BuiltInTeamRole.java new file mode 100644 index 0000000..42c18f6 --- /dev/null +++ b/src/main/java/co/lettermint/types/BuiltInTeamRole.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class BuiltInTeamRole { + /** {@code "owner"} */ + public static final BuiltInTeamRole OWNER = new BuiltInTeamRole("owner"); + + /** {@code "admin"} */ + public static final BuiltInTeamRole ADMIN = new BuiltInTeamRole("admin"); + + /** {@code "member"} */ + public static final BuiltInTeamRole MEMBER = new BuiltInTeamRole("member"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(OWNER.value, OWNER); + known.put(ADMIN.value, ADMIN); + known.put(MEMBER.value, MEMBER); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private BuiltInTeamRole(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static BuiltInTeamRole of(String value) { + Objects.requireNonNull(value, "value"); + BuiltInTeamRole known = KNOWN.get(value); + return known != null ? known : new BuiltInTeamRole(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof BuiltInTeamRole that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/Copies.java b/src/main/java/co/lettermint/types/Copies.java new file mode 100644 index 0000000..5a58041 --- /dev/null +++ b/src/main/java/co/lettermint/types/Copies.java @@ -0,0 +1,27 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** Defensive copies for the generated records. */ +final class Copies { + private Copies() { + } + + static List list(List value) { + return value == null ? null : Collections.unmodifiableList(new ArrayList<>(value)); + } + + static Map map(Map value) { + return value == null ? null : Collections.unmodifiableMap(new LinkedHashMap<>(value)); + } +} diff --git a/src/main/java/co/lettermint/types/CursorPage.java b/src/main/java/co/lettermint/types/CursorPage.java new file mode 100644 index 0000000..fb57279 --- /dev/null +++ b/src/main/java/co/lettermint/types/CursorPage.java @@ -0,0 +1,47 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * A page of a cursor-paginated list. Pass nextCursor back as the cursor query parameter to read the next page; it is null on the last page. + * + * @param data The items of this page. + * @param path Base path for paginator generated URLs. May be null. + * @param perPage Number of items shown per page. + * @param nextCursor The "cursor" that points to the next set of items. May be null. + * @param nextPageUrl May be null. + * @param prevCursor The "cursor" that points to the previous set of items. May be null. + * @param prevPageUrl May be null. + * @param the item type + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record CursorPage( + @JsonProperty("data") List data, + @JsonProperty("path") String path, + @JsonProperty("per_page") Long perPage, + @JsonProperty("next_cursor") String nextCursor, + @JsonProperty("next_page_url") String nextPageUrl, + @JsonProperty("prev_cursor") String prevCursor, + @JsonProperty("prev_page_url") String prevPageUrl +) { + /** Copies {@code data} into an unmodifiable list. */ + public CursorPage { + data = Copies.list(data); + } + + /** Whether there is a next page. */ + public boolean hasNextPage() { + return nextCursor != null && !nextCursor.isEmpty(); + } +} diff --git a/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java b/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java new file mode 100644 index 0000000..4bb774a --- /dev/null +++ b/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param success Always present. + * @param status Always present. + * @param message Human-readable confirmation. Always present. + * @param confidence Confidence of the automated removal assessment, when one ran. Optional: null when absent. + * @param ticketIdentifier The identifier of the support ticket that reviews the removal. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DeleteSuppressionResponse( + @JsonProperty("success") Boolean success, + @JsonProperty("status") DeleteSuppressionResponseStatus status, + @JsonProperty("message") String message, + @JsonProperty("confidence") Double confidence, + @JsonProperty("ticket_identifier") String ticketIdentifier +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DeleteSuppressionResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.success = success; + builder.status = status; + builder.message = message; + builder.confidence = confidence; + builder.ticketIdentifier = ticketIdentifier; + return builder; + } + + /** Builds a {@link DeleteSuppressionResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean success; + private DeleteSuppressionResponseStatus status; + private String message; + private Double confidence; + private String ticketIdentifier; + + private Builder() { + } + + /** Sets {@code success}. */ + public Builder success(Boolean success) { + this.success = success; + return this; + } + + /** Sets {@code status}. */ + public Builder status(DeleteSuppressionResponseStatus status) { + this.status = status; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code confidence}. */ + public Builder confidence(Double confidence) { + this.confidence = confidence; + return this; + } + + /** Sets {@code confidence}. */ + public Builder confidence(double confidence) { + this.confidence = confidence; + return this; + } + + /** Sets {@code ticket_identifier}. */ + public Builder ticketIdentifier(String ticketIdentifier) { + this.ticketIdentifier = ticketIdentifier; + return this; + } + + /** Returns the {@link DeleteSuppressionResponse}. */ + public DeleteSuppressionResponse build() { + return new DeleteSuppressionResponse(success, status, message, confidence, ticketIdentifier); + } + } +} diff --git a/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java b/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java new file mode 100644 index 0000000..beb85b2 --- /dev/null +++ b/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class DeleteSuppressionResponseStatus { + /** {@code "removed"} */ + public static final DeleteSuppressionResponseStatus REMOVED = new DeleteSuppressionResponseStatus("removed"); + + /** {@code "review_ticket_created"} */ + public static final DeleteSuppressionResponseStatus REVIEW_TICKET_CREATED = new DeleteSuppressionResponseStatus("review_ticket_created"); + + /** {@code "review_ticket_exists"} */ + public static final DeleteSuppressionResponseStatus REVIEW_TICKET_EXISTS = new DeleteSuppressionResponseStatus("review_ticket_exists"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(REMOVED.value, REMOVED); + known.put(REVIEW_TICKET_CREATED.value, REVIEW_TICKET_CREATED); + known.put(REVIEW_TICKET_EXISTS.value, REVIEW_TICKET_EXISTS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DeleteSuppressionResponseStatus(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DeleteSuppressionResponseStatus of(String value) { + Objects.requireNonNull(value, "value"); + DeleteSuppressionResponseStatus known = KNOWN.get(value); + return known != null ? known : new DeleteSuppressionResponseStatus(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DeleteSuppressionResponseStatus that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DeliveryMode.java b/src/main/java/co/lettermint/types/DeliveryMode.java new file mode 100644 index 0000000..ef8ab6e --- /dev/null +++ b/src/main/java/co/lettermint/types/DeliveryMode.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class DeliveryMode { + /** {@code "live"} */ + public static final DeliveryMode LIVE = new DeliveryMode("live"); + + /** {@code "sandbox"} */ + public static final DeliveryMode SANDBOX = new DeliveryMode("sandbox"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(LIVE.value, LIVE); + known.put(SANDBOX.value, SANDBOX); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DeliveryMode(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DeliveryMode of(String value) { + Objects.requireNonNull(value, "value"); + DeliveryMode known = KNOWN.get(value); + return known != null ? known : new DeliveryMode(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DeliveryMode that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DkimMode.java b/src/main/java/co/lettermint/types/DkimMode.java new file mode 100644 index 0000000..f4afe67 --- /dev/null +++ b/src/main/java/co/lettermint/types/DkimMode.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class DkimMode { + /** {@code "legacy_txt"} */ + public static final DkimMode LEGACY_TXT = new DkimMode("legacy_txt"); + + /** {@code "managed_cname"} */ + public static final DkimMode MANAGED_CNAME = new DkimMode("managed_cname"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(LEGACY_TXT.value, LEGACY_TXT); + known.put(MANAGED_CNAME.value, MANAGED_CNAME); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DkimMode(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DkimMode of(String value) { + Objects.requireNonNull(value, "value"); + DkimMode known = KNOWN.get(value); + return known != null ? known : new DkimMode(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DkimMode that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DmarcPolicy.java b/src/main/java/co/lettermint/types/DmarcPolicy.java new file mode 100644 index 0000000..54f9fe6 --- /dev/null +++ b/src/main/java/co/lettermint/types/DmarcPolicy.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class DmarcPolicy { + /** {@code "none"} */ + public static final DmarcPolicy NONE = new DmarcPolicy("none"); + + /** {@code "quarantine"} */ + public static final DmarcPolicy QUARANTINE = new DmarcPolicy("quarantine"); + + /** {@code "reject"} */ + public static final DmarcPolicy REJECT = new DmarcPolicy("reject"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(NONE.value, NONE); + known.put(QUARANTINE.value, QUARANTINE); + known.put(REJECT.value, REJECT); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DmarcPolicy(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DmarcPolicy of(String value) { + Objects.requireNonNull(value, "value"); + DmarcPolicy known = KNOWN.get(value); + return known != null ? known : new DmarcPolicy(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DmarcPolicy that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DnsRecordPurpose.java b/src/main/java/co/lettermint/types/DnsRecordPurpose.java new file mode 100644 index 0000000..39cb0a7 --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsRecordPurpose.java @@ -0,0 +1,94 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class DnsRecordPurpose { + /** {@code "return_path"} */ + public static final DnsRecordPurpose RETURN_PATH = new DnsRecordPurpose("return_path"); + + /** {@code "dmarc"} */ + public static final DnsRecordPurpose DMARC = new DnsRecordPurpose("dmarc"); + + /** {@code "dkim_legacy"} */ + public static final DnsRecordPurpose DKIM_LEGACY = new DnsRecordPurpose("dkim_legacy"); + + /** {@code "dkim_primary"} */ + public static final DnsRecordPurpose DKIM_PRIMARY = new DnsRecordPurpose("dkim_primary"); + + /** {@code "dkim_secondary"} */ + public static final DnsRecordPurpose DKIM_SECONDARY = new DnsRecordPurpose("dkim_secondary"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(RETURN_PATH.value, RETURN_PATH); + known.put(DMARC.value, DMARC); + known.put(DKIM_LEGACY.value, DKIM_LEGACY); + known.put(DKIM_PRIMARY.value, DKIM_PRIMARY); + known.put(DKIM_SECONDARY.value, DKIM_SECONDARY); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DnsRecordPurpose(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DnsRecordPurpose of(String value) { + Objects.requireNonNull(value, "value"); + DnsRecordPurpose known = KNOWN.get(value); + return known != null ? known : new DnsRecordPurpose(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DnsRecordPurpose that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DnsRecordStatus.java b/src/main/java/co/lettermint/types/DnsRecordStatus.java new file mode 100644 index 0000000..f01ff19 --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsRecordStatus.java @@ -0,0 +1,94 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * | | + * |---| + * | active <br/> The record is active and verified. | + * | failed <br/> The record could not be verified. | + * | pending <br/> The record is pending verification. | + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class DnsRecordStatus { + /** {@code "active"} */ + public static final DnsRecordStatus ACTIVE = new DnsRecordStatus("active"); + + /** {@code "failed"} */ + public static final DnsRecordStatus FAILED = new DnsRecordStatus("failed"); + + /** {@code "pending"} */ + public static final DnsRecordStatus PENDING = new DnsRecordStatus("pending"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(ACTIVE.value, ACTIVE); + known.put(FAILED.value, FAILED); + known.put(PENDING.value, PENDING); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DnsRecordStatus(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DnsRecordStatus of(String value) { + Objects.requireNonNull(value, "value"); + DnsRecordStatus known = KNOWN.get(value); + return known != null ? known : new DnsRecordStatus(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DnsRecordStatus that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java b/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java new file mode 100644 index 0000000..1fb1aff --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A DNS record that did not pass verification, with the verification details. + * + * @param message Human-readable verification error. Always present. + * @param result Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsRecordVerificationFailureResponse( + @JsonProperty("message") String message, + @JsonProperty("result") DnsVerificationResultData result +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsRecordVerificationFailureResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + builder.result = result; + return builder; + } + + /** Builds a {@link DnsRecordVerificationFailureResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + private DnsVerificationResultData result; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code result}. */ + public Builder result(DnsVerificationResultData result) { + this.result = result; + return this; + } + + /** Returns the {@link DnsRecordVerificationFailureResponse}. */ + public DnsRecordVerificationFailureResponse build() { + return new DnsRecordVerificationFailureResponse(message, result); + } + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationError.java b/src/main/java/co/lettermint/types/DnsVerificationError.java new file mode 100644 index 0000000..b18ee2c --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationError.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Why a DNS record did not pass verification. + * + * @param recordId The DNS record ID. Always present. + * @param error Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsVerificationError( + @JsonProperty("record_id") String recordId, + @JsonProperty("error") String error +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsVerificationError. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.recordId = recordId; + builder.error = error; + return builder; + } + + /** Builds a {@link DnsVerificationError}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String recordId; + private String error; + + private Builder() { + } + + /** Sets {@code record_id}. */ + public Builder recordId(String recordId) { + this.recordId = recordId; + return this; + } + + /** Sets {@code error}. */ + public Builder error(String error) { + this.error = error; + return this; + } + + /** Returns the {@link DnsVerificationError}. */ + public DnsVerificationError build() { + return new DnsVerificationError(recordId, error); + } + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java b/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java new file mode 100644 index 0000000..71051b8 --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java @@ -0,0 +1,74 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A DNS record that did not pass verification. + * + * @param id The DNS record ID. Always present. + * @param type Always present. + * @param name The record hostname. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsVerificationFailedRecord( + @JsonProperty("id") String id, + @JsonProperty("type") RecordType type, + @JsonProperty("name") String name +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsVerificationFailedRecord. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.type = type; + builder.name = name; + return builder; + } + + /** Builds a {@link DnsVerificationFailedRecord}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private RecordType type; + private String name; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code type}. */ + public Builder type(RecordType type) { + this.type = type; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Returns the {@link DnsVerificationFailedRecord}. */ + public DnsVerificationFailedRecord build() { + return new DnsVerificationFailedRecord(id, type, name); + } + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java b/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java new file mode 100644 index 0000000..040fddb --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java @@ -0,0 +1,113 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * One or more required DNS records of the domain did not pass verification. + * + * @param message Human-readable verification result. Always present. + * @param failedRecords Required records that did not pass verification. Always present. + * @param errors Verification errors of every failed record, including recommended records. Always present. + * @param failedCount The number of required records that failed. Always present. + * @param totalCount The number of required records. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsVerificationFailureResponse( + @JsonProperty("message") String message, + @JsonProperty("failed_records") List failedRecords, + @JsonProperty("errors") List errors, + @JsonProperty("failed_count") Long failedCount, + @JsonProperty("total_count") Long totalCount +) { + /** Copies lists and maps into unmodifiable collections. */ + public DnsVerificationFailureResponse { + failedRecords = Copies.list(failedRecords); + errors = Copies.list(errors); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsVerificationFailureResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + builder.failedRecords = failedRecords; + builder.errors = errors; + builder.failedCount = failedCount; + builder.totalCount = totalCount; + return builder; + } + + /** Builds a {@link DnsVerificationFailureResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + private List failedRecords; + private List errors; + private Long failedCount; + private Long totalCount; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code failed_records}. */ + public Builder failedRecords(List failedRecords) { + this.failedRecords = failedRecords; + return this; + } + + /** Sets {@code errors}. */ + public Builder errors(List errors) { + this.errors = errors; + return this; + } + + /** Sets {@code failed_count}. */ + public Builder failedCount(Long failedCount) { + this.failedCount = failedCount; + return this; + } + + /** Sets {@code failed_count}. */ + public Builder failedCount(long failedCount) { + this.failedCount = failedCount; + return this; + } + + /** Sets {@code total_count}. */ + public Builder totalCount(Long totalCount) { + this.totalCount = totalCount; + return this; + } + + /** Sets {@code total_count}. */ + public Builder totalCount(long totalCount) { + this.totalCount = totalCount; + return this; + } + + /** Returns the {@link DnsVerificationFailureResponse}. */ + public DnsVerificationFailureResponse build() { + return new DnsVerificationFailureResponse(message, failedRecords, errors, failedCount, totalCount); + } + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationResultData.java b/src/main/java/co/lettermint/types/DnsVerificationResultData.java new file mode 100644 index 0000000..10dc289 --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationResultData.java @@ -0,0 +1,112 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param dmarcSpfAlignmentIssue Always present; may be null. + * @param verified Always present. + * @param error Always present; may be null. + * @param expectedRecord Always present; may be null. + * @param foundRecord Always present; may be null. + * @param dmarcPolicyDomain Always present; may be null. + * @param dmarcEffectivePolicy Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsVerificationResultData( + @JsonProperty("dmarc_spf_alignment_issue") DnsVerificationResultDataDmarcSpfAlignmentIssue dmarcSpfAlignmentIssue, + @JsonProperty("verified") Boolean verified, + @JsonProperty("error") String error, + @JsonProperty("expected_record") String expectedRecord, + @JsonProperty("found_record") String foundRecord, + @JsonProperty("dmarc_policy_domain") String dmarcPolicyDomain, + @JsonProperty("dmarc_effective_policy") DmarcPolicy dmarcEffectivePolicy +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsVerificationResultData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.dmarcSpfAlignmentIssue = dmarcSpfAlignmentIssue; + builder.verified = verified; + builder.error = error; + builder.expectedRecord = expectedRecord; + builder.foundRecord = foundRecord; + builder.dmarcPolicyDomain = dmarcPolicyDomain; + builder.dmarcEffectivePolicy = dmarcEffectivePolicy; + return builder; + } + + /** Builds a {@link DnsVerificationResultData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private DnsVerificationResultDataDmarcSpfAlignmentIssue dmarcSpfAlignmentIssue; + private Boolean verified; + private String error; + private String expectedRecord; + private String foundRecord; + private String dmarcPolicyDomain; + private DmarcPolicy dmarcEffectivePolicy; + + private Builder() { + } + + /** Sets {@code dmarc_spf_alignment_issue}. */ + public Builder dmarcSpfAlignmentIssue(DnsVerificationResultDataDmarcSpfAlignmentIssue dmarcSpfAlignmentIssue) { + this.dmarcSpfAlignmentIssue = dmarcSpfAlignmentIssue; + return this; + } + + /** Sets {@code verified}. */ + public Builder verified(Boolean verified) { + this.verified = verified; + return this; + } + + /** Sets {@code error}. */ + public Builder error(String error) { + this.error = error; + return this; + } + + /** Sets {@code expected_record}. */ + public Builder expectedRecord(String expectedRecord) { + this.expectedRecord = expectedRecord; + return this; + } + + /** Sets {@code found_record}. */ + public Builder foundRecord(String foundRecord) { + this.foundRecord = foundRecord; + return this; + } + + /** Sets {@code dmarc_policy_domain}. */ + public Builder dmarcPolicyDomain(String dmarcPolicyDomain) { + this.dmarcPolicyDomain = dmarcPolicyDomain; + return this; + } + + /** Sets {@code dmarc_effective_policy}. */ + public Builder dmarcEffectivePolicy(DmarcPolicy dmarcEffectivePolicy) { + this.dmarcEffectivePolicy = dmarcEffectivePolicy; + return this; + } + + /** Returns the {@link DnsVerificationResultData}. */ + public DnsVerificationResultData build() { + return new DnsVerificationResultData(dmarcSpfAlignmentIssue, verified, error, expectedRecord, foundRecord, dmarcPolicyDomain, dmarcEffectivePolicy); + } + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java b/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java new file mode 100644 index 0000000..267311f --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java @@ -0,0 +1,72 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param code Always present. + * @param blocksVerification Always present. + * @param returnPathDomain Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsVerificationResultDataDmarcSpfAlignmentIssue( + @JsonProperty("code") String code, + @JsonProperty("blocks_verification") Boolean blocksVerification, + @JsonProperty("return_path_domain") String returnPathDomain +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsVerificationResultDataDmarcSpfAlignmentIssue. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.code = code; + builder.blocksVerification = blocksVerification; + builder.returnPathDomain = returnPathDomain; + return builder; + } + + /** Builds a {@link DnsVerificationResultDataDmarcSpfAlignmentIssue}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String code; + private Boolean blocksVerification; + private String returnPathDomain; + + private Builder() { + } + + /** Sets {@code code}. */ + public Builder code(String code) { + this.code = code; + return this; + } + + /** Sets {@code blocks_verification}. */ + public Builder blocksVerification(Boolean blocksVerification) { + this.blocksVerification = blocksVerification; + return this; + } + + /** Sets {@code return_path_domain}. */ + public Builder returnPathDomain(String returnPathDomain) { + this.returnPathDomain = returnPathDomain; + return this; + } + + /** Returns the {@link DnsVerificationResultDataDmarcSpfAlignmentIssue}. */ + public DnsVerificationResultDataDmarcSpfAlignmentIssue build() { + return new DnsVerificationResultDataDmarcSpfAlignmentIssue(code, blocksVerification, returnPathDomain); + } + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationScope.java b/src/main/java/co/lettermint/types/DnsVerificationScope.java new file mode 100644 index 0000000..db81cd6 --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationScope.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class DnsVerificationScope { + /** {@code "required"} */ + public static final DnsVerificationScope REQUIRED = new DnsVerificationScope("required"); + + /** {@code "recommended"} */ + public static final DnsVerificationScope RECOMMENDED = new DnsVerificationScope("recommended"); + + /** {@code "migration"} */ + public static final DnsVerificationScope MIGRATION = new DnsVerificationScope("migration"); + + /** {@code "deprecated"} */ + public static final DnsVerificationScope DEPRECATED = new DnsVerificationScope("deprecated"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(REQUIRED.value, REQUIRED); + known.put(RECOMMENDED.value, RECOMMENDED); + known.put(MIGRATION.value, MIGRATION); + known.put(DEPRECATED.value, DEPRECATED); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DnsVerificationScope(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DnsVerificationScope of(String value) { + Objects.requireNonNull(value, "value"); + DnsVerificationScope known = KNOWN.get(value); + return known != null ? known : new DnsVerificationScope(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DnsVerificationScope that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java b/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java new file mode 100644 index 0000000..15d6e77 --- /dev/null +++ b/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java @@ -0,0 +1,70 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * All required DNS records of the domain passed verification. + * + * @param message Human-readable verification result. Always present. + * @param recommendedFailedRecords Recommended records that did not pass verification. They do not block verification. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DnsVerificationSuccessResponse( + @JsonProperty("message") String message, + @JsonProperty("recommended_failed_records") List recommendedFailedRecords +) { + /** Copies lists and maps into unmodifiable collections. */ + public DnsVerificationSuccessResponse { + recommendedFailedRecords = Copies.list(recommendedFailedRecords); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DnsVerificationSuccessResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + builder.recommendedFailedRecords = recommendedFailedRecords; + return builder; + } + + /** Builds a {@link DnsVerificationSuccessResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + private List recommendedFailedRecords; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code recommended_failed_records}. */ + public Builder recommendedFailedRecords(List recommendedFailedRecords) { + this.recommendedFailedRecords = recommendedFailedRecords; + return this; + } + + /** Returns the {@link DnsVerificationSuccessResponse}. */ + public DnsVerificationSuccessResponse build() { + return new DnsVerificationSuccessResponse(message, recommendedFailedRecords); + } + } +} diff --git a/src/main/java/co/lettermint/types/DomainData.java b/src/main/java/co/lettermint/types/DomainData.java new file mode 100644 index 0000000..65a0482 --- /dev/null +++ b/src/main/java/co/lettermint/types/DomainData.java @@ -0,0 +1,129 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param domain Always present. + * @param dkimMode Always present. + * @param rotationReady Always present. + * @param statusChangedAt Always present; may be null. + * @param dnsRecords Optional: null when absent. + * @param projects Optional: null when absent. + * @param createdAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DomainData( + @JsonProperty("id") String id, + @JsonProperty("domain") String domain, + @JsonProperty("dkim_mode") DkimMode dkimMode, + @JsonProperty("rotation_ready") Boolean rotationReady, + @JsonProperty("status_changed_at") String statusChangedAt, + @JsonProperty("dns_records") List dnsRecords, + @JsonProperty("projects") List projects, + @JsonProperty("created_at") String createdAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public DomainData { + dnsRecords = Copies.list(dnsRecords); + projects = Copies.list(projects); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DomainData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.domain = domain; + builder.dkimMode = dkimMode; + builder.rotationReady = rotationReady; + builder.statusChangedAt = statusChangedAt; + builder.dnsRecords = dnsRecords; + builder.projects = projects; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link DomainData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String domain; + private DkimMode dkimMode; + private Boolean rotationReady; + private String statusChangedAt; + private List dnsRecords; + private List projects; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code domain}. */ + public Builder domain(String domain) { + this.domain = domain; + return this; + } + + /** Sets {@code dkim_mode}. */ + public Builder dkimMode(DkimMode dkimMode) { + this.dkimMode = dkimMode; + return this; + } + + /** Sets {@code rotation_ready}. */ + public Builder rotationReady(Boolean rotationReady) { + this.rotationReady = rotationReady; + return this; + } + + /** Sets {@code status_changed_at}. */ + public Builder statusChangedAt(String statusChangedAt) { + this.statusChangedAt = statusChangedAt; + return this; + } + + /** Sets {@code dns_records}. */ + public Builder dnsRecords(List dnsRecords) { + this.dnsRecords = dnsRecords; + return this; + } + + /** Sets {@code projects}. */ + public Builder projects(List projects) { + this.projects = projects; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link DomainData}. */ + public DomainData build() { + return new DomainData(id, domain, dkimMode, rotationReady, statusChangedAt, dnsRecords, projects, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/DomainDataProjectsItem.java b/src/main/java/co/lettermint/types/DomainDataProjectsItem.java new file mode 100644 index 0000000..8156ddc --- /dev/null +++ b/src/main/java/co/lettermint/types/DomainDataProjectsItem.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param name Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DomainDataProjectsItem( + @JsonProperty("id") String id, + @JsonProperty("name") String name +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DomainDataProjectsItem. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + return builder; + } + + /** Builds a {@link DomainDataProjectsItem}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Returns the {@link DomainDataProjectsItem}. */ + public DomainDataProjectsItem build() { + return new DomainDataProjectsItem(id, name); + } + } +} diff --git a/src/main/java/co/lettermint/types/DomainDnsRecordData.java b/src/main/java/co/lettermint/types/DomainDnsRecordData.java new file mode 100644 index 0000000..ca79133 --- /dev/null +++ b/src/main/java/co/lettermint/types/DomainDnsRecordData.java @@ -0,0 +1,152 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param type Always present. + * @param hostname Always present. + * @param fqdn Always present. + * @param content Always present. + * @param status Always present. + * @param purpose Always present. + * @param verificationScope Always present. + * @param requiredForVerification Always present. + * @param verifiedAt Always present; may be null. + * @param lastCheckedAt Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DomainDnsRecordData( + @JsonProperty("id") String id, + @JsonProperty("type") RecordType type, + @JsonProperty("hostname") String hostname, + @JsonProperty("fqdn") String fqdn, + @JsonProperty("content") String content, + @JsonProperty("status") DnsRecordStatus status, + @JsonProperty("purpose") DnsRecordPurpose purpose, + @JsonProperty("verification_scope") DnsVerificationScope verificationScope, + @JsonProperty("required_for_verification") Boolean requiredForVerification, + @JsonProperty("verified_at") String verifiedAt, + @JsonProperty("last_checked_at") String lastCheckedAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DomainDnsRecordData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.type = type; + builder.hostname = hostname; + builder.fqdn = fqdn; + builder.content = content; + builder.status = status; + builder.purpose = purpose; + builder.verificationScope = verificationScope; + builder.requiredForVerification = requiredForVerification; + builder.verifiedAt = verifiedAt; + builder.lastCheckedAt = lastCheckedAt; + return builder; + } + + /** Builds a {@link DomainDnsRecordData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private RecordType type; + private String hostname; + private String fqdn; + private String content; + private DnsRecordStatus status; + private DnsRecordPurpose purpose; + private DnsVerificationScope verificationScope; + private Boolean requiredForVerification; + private String verifiedAt; + private String lastCheckedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code type}. */ + public Builder type(RecordType type) { + this.type = type; + return this; + } + + /** Sets {@code hostname}. */ + public Builder hostname(String hostname) { + this.hostname = hostname; + return this; + } + + /** Sets {@code fqdn}. */ + public Builder fqdn(String fqdn) { + this.fqdn = fqdn; + return this; + } + + /** Sets {@code content}. */ + public Builder content(String content) { + this.content = content; + return this; + } + + /** Sets {@code status}. */ + public Builder status(DnsRecordStatus status) { + this.status = status; + return this; + } + + /** Sets {@code purpose}. */ + public Builder purpose(DnsRecordPurpose purpose) { + this.purpose = purpose; + return this; + } + + /** Sets {@code verification_scope}. */ + public Builder verificationScope(DnsVerificationScope verificationScope) { + this.verificationScope = verificationScope; + return this; + } + + /** Sets {@code required_for_verification}. */ + public Builder requiredForVerification(Boolean requiredForVerification) { + this.requiredForVerification = requiredForVerification; + return this; + } + + /** Sets {@code verified_at}. */ + public Builder verifiedAt(String verifiedAt) { + this.verifiedAt = verifiedAt; + return this; + } + + /** Sets {@code last_checked_at}. */ + public Builder lastCheckedAt(String lastCheckedAt) { + this.lastCheckedAt = lastCheckedAt; + return this; + } + + /** Returns the {@link DomainDnsRecordData}. */ + public DomainDnsRecordData build() { + return new DomainDnsRecordData(id, type, hostname, fqdn, content, status, purpose, verificationScope, requiredForVerification, verifiedAt, lastCheckedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/DomainListData.java b/src/main/java/co/lettermint/types/DomainListData.java new file mode 100644 index 0000000..0cb3434 --- /dev/null +++ b/src/main/java/co/lettermint/types/DomainListData.java @@ -0,0 +1,102 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param domain Always present. + * @param status Always present. + * @param dkimMode Always present. + * @param statusChangedAt Always present; may be null. + * @param createdAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DomainListData( + @JsonProperty("id") String id, + @JsonProperty("domain") String domain, + @JsonProperty("status") DomainStatus status, + @JsonProperty("dkim_mode") DkimMode dkimMode, + @JsonProperty("status_changed_at") String statusChangedAt, + @JsonProperty("created_at") String createdAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DomainListData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.domain = domain; + builder.status = status; + builder.dkimMode = dkimMode; + builder.statusChangedAt = statusChangedAt; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link DomainListData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String domain; + private DomainStatus status; + private DkimMode dkimMode; + private String statusChangedAt; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code domain}. */ + public Builder domain(String domain) { + this.domain = domain; + return this; + } + + /** Sets {@code status}. */ + public Builder status(DomainStatus status) { + this.status = status; + return this; + } + + /** Sets {@code dkim_mode}. */ + public Builder dkimMode(DkimMode dkimMode) { + this.dkimMode = dkimMode; + return this; + } + + /** Sets {@code status_changed_at}. */ + public Builder statusChangedAt(String statusChangedAt) { + this.statusChangedAt = statusChangedAt; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link DomainListData}. */ + public DomainListData build() { + return new DomainListData(id, domain, status, dkimMode, statusChangedAt, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/DomainMutationResponse.java b/src/main/java/co/lettermint/types/DomainMutationResponse.java new file mode 100644 index 0000000..3159015 --- /dev/null +++ b/src/main/java/co/lettermint/types/DomainMutationResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The domain after a change, with a confirmation message. + * + * @param data Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record DomainMutationResponse( + @JsonProperty("data") DomainData data, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this DomainMutationResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + return builder; + } + + /** Builds a {@link DomainMutationResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private DomainData data; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(DomainData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link DomainMutationResponse}. */ + public DomainMutationResponse build() { + return new DomainMutationResponse(data, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/DomainStatus.java b/src/main/java/co/lettermint/types/DomainStatus.java new file mode 100644 index 0000000..55835f7 --- /dev/null +++ b/src/main/java/co/lettermint/types/DomainStatus.java @@ -0,0 +1,99 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * | | + * |---| + * | verified <br/> The domain is active and verified. | + * | partially_verified <br/> Some DNS records of the domain could not be verified. | + * | pending_verification <br/> The domain is new and verification is pending. | + * | failed_verification <br/> The domain verification failed. | + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class DomainStatus { + /** {@code "verified"} */ + public static final DomainStatus VERIFIED = new DomainStatus("verified"); + + /** {@code "partially_verified"} */ + public static final DomainStatus PARTIALLY_VERIFIED = new DomainStatus("partially_verified"); + + /** {@code "pending_verification"} */ + public static final DomainStatus PENDING_VERIFICATION = new DomainStatus("pending_verification"); + + /** {@code "failed_verification"} */ + public static final DomainStatus FAILED_VERIFICATION = new DomainStatus("failed_verification"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(VERIFIED.value, VERIFIED); + known.put(PARTIALLY_VERIFIED.value, PARTIALLY_VERIFIED); + known.put(PENDING_VERIFICATION.value, PENDING_VERIFICATION); + known.put(FAILED_VERIFICATION.value, FAILED_VERIFICATION); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private DomainStatus(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static DomainStatus of(String value) { + Objects.requireNonNull(value, "value"); + DomainStatus known = KNOWN.get(value); + return known != null ? known : new DomainStatus(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof DomainStatus that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ErrorMessage.java b/src/main/java/co/lettermint/types/ErrorMessage.java new file mode 100644 index 0000000..6e9e716 --- /dev/null +++ b/src/main/java/co/lettermint/types/ErrorMessage.java @@ -0,0 +1,54 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Error with only a message. + * + * @param message Error overview. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ErrorMessage( + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ErrorMessage. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + return builder; + } + + /** Builds a {@link ErrorMessage}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link ErrorMessage}. */ + public ErrorMessage build() { + return new ErrorMessage(message); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetDomainQuery.java b/src/main/java/co/lettermint/types/GetDomainQuery.java new file mode 100644 index 0000000..b81e756 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetDomainQuery.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /domains/{domainId} (getDomain). + * + * @param include Optional: null omits it. Sent as include. + */ +public record GetDomainQuery( + List include +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public GetDomainQuery { + include = Copies.list(include); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("include", include); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this GetDomainQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.include = include; + return builder; + } + + /** Builds a {@link GetDomainQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List include; + + private Builder() { + } + + /** Sets {@code include}. */ + public Builder include(List include) { + this.include = include; + return this; + } + + /** Returns the {@link GetDomainQuery}. */ + public GetDomainQuery build() { + return new GetDomainQuery(include); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java new file mode 100644 index 0000000..a2c9447 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class GetDomainQueryIncludeItem { + /** {@code "dnsRecords"} */ + public static final GetDomainQueryIncludeItem DNS_RECORDS = new GetDomainQueryIncludeItem("dnsRecords"); + + /** {@code "projects"} */ + public static final GetDomainQueryIncludeItem PROJECTS = new GetDomainQueryIncludeItem("projects"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(DNS_RECORDS.value, DNS_RECORDS); + known.put(PROJECTS.value, PROJECTS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private GetDomainQueryIncludeItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static GetDomainQueryIncludeItem of(String value) { + Objects.requireNonNull(value, "value"); + GetDomainQueryIncludeItem known = KNOWN.get(value); + return known != null ? known : new GetDomainQueryIncludeItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof GetDomainQueryIncludeItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/GetProjectQuery.java b/src/main/java/co/lettermint/types/GetProjectQuery.java new file mode 100644 index 0000000..7a3bba0 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetProjectQuery.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /projects/{projectId} (getProject). + * + * @param include Optional: null omits it. Sent as include. + */ +public record GetProjectQuery( + List include +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public GetProjectQuery { + include = Copies.list(include); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("include", include); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this GetProjectQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.include = include; + return builder; + } + + /** Builds a {@link GetProjectQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List include; + + private Builder() { + } + + /** Sets {@code include}. */ + public Builder include(List include) { + this.include = include; + return this; + } + + /** Returns the {@link GetProjectQuery}. */ + public GetProjectQuery build() { + return new GetProjectQuery(include); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java new file mode 100644 index 0000000..5634311 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java @@ -0,0 +1,110 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class GetProjectQueryIncludeItem { + /** {@code "routes"} */ + public static final GetProjectQueryIncludeItem ROUTES = new GetProjectQueryIncludeItem("routes"); + + /** {@code "routesCount"} */ + public static final GetProjectQueryIncludeItem ROUTES_COUNT = new GetProjectQueryIncludeItem("routesCount"); + + /** {@code "routesExists"} */ + public static final GetProjectQueryIncludeItem ROUTES_EXISTS = new GetProjectQueryIncludeItem("routesExists"); + + /** {@code "domains"} */ + public static final GetProjectQueryIncludeItem DOMAINS = new GetProjectQueryIncludeItem("domains"); + + /** {@code "domainsCount"} */ + public static final GetProjectQueryIncludeItem DOMAINS_COUNT = new GetProjectQueryIncludeItem("domainsCount"); + + /** {@code "domainsExists"} */ + public static final GetProjectQueryIncludeItem DOMAINS_EXISTS = new GetProjectQueryIncludeItem("domainsExists"); + + /** {@code "messageStats"} */ + public static final GetProjectQueryIncludeItem MESSAGE_STATS = new GetProjectQueryIncludeItem("messageStats"); + + /** {@code "messageStatsCount"} */ + public static final GetProjectQueryIncludeItem MESSAGE_STATS_COUNT = new GetProjectQueryIncludeItem("messageStatsCount"); + + /** {@code "messageStatsExists"} */ + public static final GetProjectQueryIncludeItem MESSAGE_STATS_EXISTS = new GetProjectQueryIncludeItem("messageStatsExists"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(ROUTES.value, ROUTES); + known.put(ROUTES_COUNT.value, ROUTES_COUNT); + known.put(ROUTES_EXISTS.value, ROUTES_EXISTS); + known.put(DOMAINS.value, DOMAINS); + known.put(DOMAINS_COUNT.value, DOMAINS_COUNT); + known.put(DOMAINS_EXISTS.value, DOMAINS_EXISTS); + known.put(MESSAGE_STATS.value, MESSAGE_STATS); + known.put(MESSAGE_STATS_COUNT.value, MESSAGE_STATS_COUNT); + known.put(MESSAGE_STATS_EXISTS.value, MESSAGE_STATS_EXISTS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private GetProjectQueryIncludeItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static GetProjectQueryIncludeItem of(String value) { + Objects.requireNonNull(value, "value"); + GetProjectQueryIncludeItem known = KNOWN.get(value); + return known != null ? known : new GetProjectQueryIncludeItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof GetProjectQueryIncludeItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/GetReportForwardingResponse.java b/src/main/java/co/lettermint/types/GetReportForwardingResponse.java new file mode 100644 index 0000000..e946ee1 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetReportForwardingResponse.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record GetReportForwardingResponse( + @JsonProperty("data") ReportForwardingResource data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this GetReportForwardingResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link GetReportForwardingResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ReportForwardingResource data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ReportForwardingResource data) { + this.data = data; + return this; + } + + /** Returns the {@link GetReportForwardingResponse}. */ + public GetReportForwardingResponse build() { + return new GetReportForwardingResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetRouteQuery.java b/src/main/java/co/lettermint/types/GetRouteQuery.java new file mode 100644 index 0000000..bf31315 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetRouteQuery.java @@ -0,0 +1,75 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /routes/{routeId} (getRoute). + * + * @param includeMachine Include legacy machine observations in open and click totals. Privacy opens are reported in the observed and privacy fields without this option. Optional: null omits it. Sent as include_machine. + * @param include Optional: null omits it. Sent as include. + */ +public record GetRouteQuery( + Boolean includeMachine, + List include +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public GetRouteQuery { + include = Copies.list(include); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("include_machine", includeMachine); + parameters.put("include", include); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this GetRouteQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.includeMachine = includeMachine; + builder.include = include; + return builder; + } + + /** Builds a {@link GetRouteQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean includeMachine; + private List include; + + private Builder() { + } + + /** Sets {@code include_machine}. */ + public Builder includeMachine(Boolean includeMachine) { + this.includeMachine = includeMachine; + return this; + } + + /** Sets {@code include}. */ + public Builder include(List include) { + this.include = include; + return this; + } + + /** Returns the {@link GetRouteQuery}. */ + public GetRouteQuery build() { + return new GetRouteQuery(includeMachine, include); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java new file mode 100644 index 0000000..4d186fa --- /dev/null +++ b/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class GetRouteQueryIncludeItem { + /** {@code "project"} */ + public static final GetRouteQueryIncludeItem PROJECT = new GetRouteQueryIncludeItem("project"); + + /** {@code "projectCount"} */ + public static final GetRouteQueryIncludeItem PROJECT_COUNT = new GetRouteQueryIncludeItem("projectCount"); + + /** {@code "projectExists"} */ + public static final GetRouteQueryIncludeItem PROJECT_EXISTS = new GetRouteQueryIncludeItem("projectExists"); + + /** {@code "statistics"} */ + public static final GetRouteQueryIncludeItem STATISTICS = new GetRouteQueryIncludeItem("statistics"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PROJECT.value, PROJECT); + known.put(PROJECT_COUNT.value, PROJECT_COUNT); + known.put(PROJECT_EXISTS.value, PROJECT_EXISTS); + known.put(STATISTICS.value, STATISTICS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private GetRouteQueryIncludeItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static GetRouteQueryIncludeItem of(String value) { + Objects.requireNonNull(value, "value"); + GetRouteQueryIncludeItem known = KNOWN.get(value); + return known != null ? known : new GetRouteQueryIncludeItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof GetRouteQueryIncludeItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/GetStatsQuery.java b/src/main/java/co/lettermint/types/GetStatsQuery.java new file mode 100644 index 0000000..c3d3edc --- /dev/null +++ b/src/main/java/co/lettermint/types/GetStatsQuery.java @@ -0,0 +1,92 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Query parameters of GET /stats (getStats). + * + * @param from Required. Sent as from. + * @param to Required. Sent as to. + * @param projectId Optional and nullable: null when absent or null. Sent as project_id. + * @param includeMachine Optional: null omits it. Sent as include_machine. + */ +public record GetStatsQuery( + String from, + String to, + String projectId, + Boolean includeMachine +) implements QueryParameters { + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("from", from); + parameters.put("to", to); + parameters.put("project_id", projectId); + parameters.put("include_machine", includeMachine); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this GetStatsQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.from = from; + builder.to = to; + builder.projectId = projectId; + builder.includeMachine = includeMachine; + return builder; + } + + /** Builds a {@link GetStatsQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String from; + private String to; + private String projectId; + private Boolean includeMachine; + + private Builder() { + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(String to) { + this.to = to; + return this; + } + + /** Sets {@code project_id}. */ + public Builder projectId(String projectId) { + this.projectId = projectId; + return this; + } + + /** Sets {@code include_machine}. */ + public Builder includeMachine(Boolean includeMachine) { + this.includeMachine = includeMachine; + return this; + } + + /** Returns the {@link GetStatsQuery}. */ + public GetStatsQuery build() { + return new GetStatsQuery(from, to, projectId, includeMachine); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetTeamQuery.java b/src/main/java/co/lettermint/types/GetTeamQuery.java new file mode 100644 index 0000000..89cd848 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetTeamQuery.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /team (getTeam). + * + * @param include Optional: null omits it. Sent as include. + */ +public record GetTeamQuery( + List include +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public GetTeamQuery { + include = Copies.list(include); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("include", include); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this GetTeamQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.include = include; + return builder; + } + + /** Builds a {@link GetTeamQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List include; + + private Builder() { + } + + /** Sets {@code include}. */ + public Builder include(List include) { + this.include = include; + return this; + } + + /** Returns the {@link GetTeamQuery}. */ + public GetTeamQuery build() { + return new GetTeamQuery(include); + } + } +} diff --git a/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java new file mode 100644 index 0000000..1a8c902 --- /dev/null +++ b/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class GetTeamQueryIncludeItem { + /** {@code "features"} */ + public static final GetTeamQueryIncludeItem FEATURES = new GetTeamQueryIncludeItem("features"); + + /** {@code "addons"} */ + public static final GetTeamQueryIncludeItem ADDONS = new GetTeamQueryIncludeItem("addons"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(FEATURES.value, FEATURES); + known.put(ADDONS.value, ADDONS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private GetTeamQueryIncludeItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static GetTeamQueryIncludeItem of(String value) { + Objects.requireNonNull(value, "value"); + GetTeamQueryIncludeItem known = KNOWN.get(value); + return known != null ? known : new GetTeamQueryIncludeItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof GetTeamQueryIncludeItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/InboundDomainVerification.java b/src/main/java/co/lettermint/types/InboundDomainVerification.java new file mode 100644 index 0000000..552d68b --- /dev/null +++ b/src/main/java/co/lettermint/types/InboundDomainVerification.java @@ -0,0 +1,91 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * Whether the inbound domain MX records point to Lettermint. The MX record lists are only returned when verification fails. + * + * @param verified Always present. + * @param message Human-readable verification result. Always present. + * @param expectedMxRecords The MX records the inbound domain must publish. Optional: null when absent. + * @param foundMxRecords The MX records found for the inbound domain. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record InboundDomainVerification( + @JsonProperty("verified") Boolean verified, + @JsonProperty("message") String message, + @JsonProperty("expected_mx_records") List expectedMxRecords, + @JsonProperty("found_mx_records") List foundMxRecords +) { + /** Copies lists and maps into unmodifiable collections. */ + public InboundDomainVerification { + expectedMxRecords = Copies.list(expectedMxRecords); + foundMxRecords = Copies.list(foundMxRecords); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this InboundDomainVerification. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.verified = verified; + builder.message = message; + builder.expectedMxRecords = expectedMxRecords; + builder.foundMxRecords = foundMxRecords; + return builder; + } + + /** Builds a {@link InboundDomainVerification}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean verified; + private String message; + private List expectedMxRecords; + private List foundMxRecords; + + private Builder() { + } + + /** Sets {@code verified}. */ + public Builder verified(Boolean verified) { + this.verified = verified; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code expected_mx_records}. */ + public Builder expectedMxRecords(List expectedMxRecords) { + this.expectedMxRecords = expectedMxRecords; + return this; + } + + /** Sets {@code found_mx_records}. */ + public Builder foundMxRecords(List foundMxRecords) { + this.foundMxRecords = foundMxRecords; + return this; + } + + /** Returns the {@link InboundDomainVerification}. */ + public InboundDomainVerification build() { + return new InboundDomainVerification(verified, message, expectedMxRecords, foundMxRecords); + } + } +} diff --git a/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java b/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java new file mode 100644 index 0000000..8690a14 --- /dev/null +++ b/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java @@ -0,0 +1,54 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The result of an inbound domain MX verification. + * + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record InboundDomainVerificationResponse( + @JsonProperty("data") InboundDomainVerification data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this InboundDomainVerificationResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link InboundDomainVerificationResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private InboundDomainVerification data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(InboundDomainVerification data) { + this.data = data; + return this; + } + + /** Returns the {@link InboundDomainVerificationResponse}. */ + public InboundDomainVerificationResponse build() { + return new InboundDomainVerificationResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/InitialRoutes.java b/src/main/java/co/lettermint/types/InitialRoutes.java new file mode 100644 index 0000000..b6610ae --- /dev/null +++ b/src/main/java/co/lettermint/types/InitialRoutes.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class InitialRoutes { + /** {@code "both"} */ + public static final InitialRoutes BOTH = new InitialRoutes("both"); + + /** {@code "transactional"} */ + public static final InitialRoutes TRANSACTIONAL = new InitialRoutes("transactional"); + + /** {@code "broadcast"} */ + public static final InitialRoutes BROADCAST = new InitialRoutes("broadcast"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(BOTH.value, BOTH); + known.put(TRANSACTIONAL.value, TRANSACTIONAL); + known.put(BROADCAST.value, BROADCAST); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private InitialRoutes(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static InitialRoutes of(String value) { + Objects.requireNonNull(value, "value"); + InitialRoutes known = KNOWN.get(value); + return known != null ? known : new InitialRoutes(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof InitialRoutes that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListDomainsQuery.java b/src/main/java/co/lettermint/types/ListDomainsQuery.java new file mode 100644 index 0000000..597689f --- /dev/null +++ b/src/main/java/co/lettermint/types/ListDomainsQuery.java @@ -0,0 +1,125 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /domains (listDomains). + * + * @param pageSize The number of results that will be returned per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor The cursor to start the pagination from. Optional: null omits it. Sent as page[cursor]. + * @param sort Optional: null omits it. Sent as sort. + * @param filterProject Filter by project ID. Optional: null omits it. Sent as filter[project]. + * @param filterStatus Optional: null omits it. Sent as filter[status]. + * @param filterDomain Search by domain name (partial match, case insensitive). Optional: null omits it. Sent as filter[domain]. + */ +public record ListDomainsQuery( + Long pageSize, + String pageCursor, + List sort, + String filterProject, + DomainStatus filterStatus, + String filterDomain +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListDomainsQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + parameters.put("sort", sort); + parameters.put("filter[project]", filterProject); + parameters.put("filter[status]", filterStatus); + parameters.put("filter[domain]", filterDomain); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListDomainsQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + builder.sort = sort; + builder.filterProject = filterProject; + builder.filterStatus = filterStatus; + builder.filterDomain = filterDomain; + return builder; + } + + /** Builds a {@link ListDomainsQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String pageCursor; + private List sort; + private String filterProject; + private DomainStatus filterStatus; + private String filterDomain; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Sets {@code filter[project]}. */ + public Builder filterProject(String filterProject) { + this.filterProject = filterProject; + return this; + } + + /** Sets {@code filter[status]}. */ + public Builder filterStatus(DomainStatus filterStatus) { + this.filterStatus = filterStatus; + return this; + } + + /** Sets {@code filter[domain]}. */ + public Builder filterDomain(String filterDomain) { + this.filterDomain = filterDomain; + return this; + } + + /** Returns the {@link ListDomainsQuery}. */ + public ListDomainsQuery build() { + return new ListDomainsQuery(pageSize, pageCursor, sort, filterProject, filterStatus, filterDomain); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java b/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java new file mode 100644 index 0000000..cc6cf6f --- /dev/null +++ b/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListDomainsQuerySortItem { + /** {@code "domain"} */ + public static final ListDomainsQuerySortItem DOMAIN = new ListDomainsQuerySortItem("domain"); + + /** {@code "-domain"} */ + public static final ListDomainsQuerySortItem DOMAIN_DESC = new ListDomainsQuerySortItem("-domain"); + + /** {@code "created_at"} */ + public static final ListDomainsQuerySortItem CREATED_AT = new ListDomainsQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListDomainsQuerySortItem CREATED_AT_DESC = new ListDomainsQuerySortItem("-created_at"); + + /** {@code "status_changed_at"} */ + public static final ListDomainsQuerySortItem STATUS_CHANGED_AT = new ListDomainsQuerySortItem("status_changed_at"); + + /** {@code "-status_changed_at"} */ + public static final ListDomainsQuerySortItem STATUS_CHANGED_AT_DESC = new ListDomainsQuerySortItem("-status_changed_at"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(DOMAIN.value, DOMAIN); + known.put(DOMAIN_DESC.value, DOMAIN_DESC); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + known.put(STATUS_CHANGED_AT.value, STATUS_CHANGED_AT); + known.put(STATUS_CHANGED_AT_DESC.value, STATUS_CHANGED_AT_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListDomainsQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListDomainsQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListDomainsQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListDomainsQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListDomainsQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListMessageEventsQuery.java b/src/main/java/co/lettermint/types/ListMessageEventsQuery.java new file mode 100644 index 0000000..1907b97 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListMessageEventsQuery.java @@ -0,0 +1,103 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /messages/{messageId}/events (listMessageEvents). + * + * @param pageSize The number of results that will be returned per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor The cursor to start the pagination from. Optional: null omits it. Sent as page[cursor]. + * @param includeMachineEvents Include security scanner, preview, and other machine-only tracking events. Supported privacy opens are included without this option. Optional: null omits it. Sent as include_machine_events. + * @param sort Optional: null omits it. Sent as sort. + */ +public record ListMessageEventsQuery( + Long pageSize, + String pageCursor, + Boolean includeMachineEvents, + List sort +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListMessageEventsQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + parameters.put("include_machine_events", includeMachineEvents); + parameters.put("sort", sort); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListMessageEventsQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + builder.includeMachineEvents = includeMachineEvents; + builder.sort = sort; + return builder; + } + + /** Builds a {@link ListMessageEventsQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String pageCursor; + private Boolean includeMachineEvents; + private List sort; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Sets {@code include_machine_events}. */ + public Builder includeMachineEvents(Boolean includeMachineEvents) { + this.includeMachineEvents = includeMachineEvents; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Returns the {@link ListMessageEventsQuery}. */ + public ListMessageEventsQuery build() { + return new ListMessageEventsQuery(pageSize, pageCursor, includeMachineEvents, sort); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java b/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java new file mode 100644 index 0000000..58da925 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListMessageEventsQuerySortItem { + /** {@code "timestamp"} */ + public static final ListMessageEventsQuerySortItem TIMESTAMP = new ListMessageEventsQuerySortItem("timestamp"); + + /** {@code "-timestamp"} */ + public static final ListMessageEventsQuerySortItem TIMESTAMP_DESC = new ListMessageEventsQuerySortItem("-timestamp"); + + /** {@code "event"} */ + public static final ListMessageEventsQuerySortItem EVENT = new ListMessageEventsQuerySortItem("event"); + + /** {@code "-event"} */ + public static final ListMessageEventsQuerySortItem EVENT_DESC = new ListMessageEventsQuerySortItem("-event"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TIMESTAMP.value, TIMESTAMP); + known.put(TIMESTAMP_DESC.value, TIMESTAMP_DESC); + known.put(EVENT.value, EVENT); + known.put(EVENT_DESC.value, EVENT_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListMessageEventsQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListMessageEventsQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListMessageEventsQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListMessageEventsQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListMessageEventsQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListMessagesQuery.java b/src/main/java/co/lettermint/types/ListMessagesQuery.java new file mode 100644 index 0000000..d25639c --- /dev/null +++ b/src/main/java/co/lettermint/types/ListMessagesQuery.java @@ -0,0 +1,279 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /messages (listMessages). + * + * @param sort Optional: null omits it. Sent as sort. + * @param filterSearch Search in sender, recipients, and subject. Optional: null omits it. Sent as filter[search]. + * @param filterTags0Name Exact tag name. Add more numbered pairs to match all pairs. Optional: null omits it. Sent as filter[tags][0][name]. + * @param filterTags0Value Exact tag value. Optional: null omits it. Sent as filter[tags][0][value]. + * @param filterFromEmail Search by sender email (partial match). Optional: null omits it. Sent as filter[from_email]. + * @param filterSubject Search by subject (partial match). Optional: null omits it. Sent as filter[subject]. + * @param pageSize Number of results per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor Cursor for the next or previous page. Optional: null omits it. Sent as page[cursor]. + * @param filter Optional: null omits it. Sent as filter. + * @param filterTags Optional: null omits it. Sent as filter[tags]. + * @param filterOverdue Optional: null omits it. Sent as filter[overdue]. + * @param filterProject Filter by project ID. Optional: null omits it. Sent as filter[project]. + * @param filterType Optional: null omits it. Sent as filter[type]. + * @param filterStatus Optional: null omits it. Sent as filter[status]. + * @param filterDeliveryMode Optional: null omits it. Sent as filter[delivery_mode]. + * @param filterRouteId Filter by route ID. Optional: null omits it. Sent as filter[route_id]. + * @param filterDomainId Filter by domain ID. Optional: null omits it. Sent as filter[domain_id]. + * @param filterTag Filter by tag name. Optional: null omits it. Sent as filter[tag]. + * @param filterFromDate Filter messages created after this date. Optional: null omits it. Sent as filter[from_date]. + * @param filterToDate Filter messages created before this date. Optional: null omits it. Sent as filter[to_date]. + */ +public record ListMessagesQuery( + List sort, + String filterSearch, + String filterTags0Name, + String filterTags0Value, + String filterFromEmail, + String filterSubject, + Long pageSize, + String pageCursor, + ListMessagesQueryFilter filter, + String filterTags, + String filterOverdue, + String filterProject, + MessageType filterType, + MessageStatus filterStatus, + DeliveryMode filterDeliveryMode, + String filterRouteId, + String filterDomainId, + String filterTag, + String filterFromDate, + String filterToDate +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListMessagesQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("sort", sort); + parameters.put("filter[search]", filterSearch); + parameters.put("filter[tags][0][name]", filterTags0Name); + parameters.put("filter[tags][0][value]", filterTags0Value); + parameters.put("filter[from_email]", filterFromEmail); + parameters.put("filter[subject]", filterSubject); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + parameters.put("filter", filter); + parameters.put("filter[tags]", filterTags); + parameters.put("filter[overdue]", filterOverdue); + parameters.put("filter[project]", filterProject); + parameters.put("filter[type]", filterType); + parameters.put("filter[status]", filterStatus); + parameters.put("filter[delivery_mode]", filterDeliveryMode); + parameters.put("filter[route_id]", filterRouteId); + parameters.put("filter[domain_id]", filterDomainId); + parameters.put("filter[tag]", filterTag); + parameters.put("filter[from_date]", filterFromDate); + parameters.put("filter[to_date]", filterToDate); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListMessagesQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.sort = sort; + builder.filterSearch = filterSearch; + builder.filterTags0Name = filterTags0Name; + builder.filterTags0Value = filterTags0Value; + builder.filterFromEmail = filterFromEmail; + builder.filterSubject = filterSubject; + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + builder.filter = filter; + builder.filterTags = filterTags; + builder.filterOverdue = filterOverdue; + builder.filterProject = filterProject; + builder.filterType = filterType; + builder.filterStatus = filterStatus; + builder.filterDeliveryMode = filterDeliveryMode; + builder.filterRouteId = filterRouteId; + builder.filterDomainId = filterDomainId; + builder.filterTag = filterTag; + builder.filterFromDate = filterFromDate; + builder.filterToDate = filterToDate; + return builder; + } + + /** Builds a {@link ListMessagesQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List sort; + private String filterSearch; + private String filterTags0Name; + private String filterTags0Value; + private String filterFromEmail; + private String filterSubject; + private Long pageSize; + private String pageCursor; + private ListMessagesQueryFilter filter; + private String filterTags; + private String filterOverdue; + private String filterProject; + private MessageType filterType; + private MessageStatus filterStatus; + private DeliveryMode filterDeliveryMode; + private String filterRouteId; + private String filterDomainId; + private String filterTag; + private String filterFromDate; + private String filterToDate; + + private Builder() { + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Sets {@code filter[search]}. */ + public Builder filterSearch(String filterSearch) { + this.filterSearch = filterSearch; + return this; + } + + /** Sets {@code filter[tags][0][name]}. */ + public Builder filterTags0Name(String filterTags0Name) { + this.filterTags0Name = filterTags0Name; + return this; + } + + /** Sets {@code filter[tags][0][value]}. */ + public Builder filterTags0Value(String filterTags0Value) { + this.filterTags0Value = filterTags0Value; + return this; + } + + /** Sets {@code filter[from_email]}. */ + public Builder filterFromEmail(String filterFromEmail) { + this.filterFromEmail = filterFromEmail; + return this; + } + + /** Sets {@code filter[subject]}. */ + public Builder filterSubject(String filterSubject) { + this.filterSubject = filterSubject; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Sets {@code filter}. */ + public Builder filter(ListMessagesQueryFilter filter) { + this.filter = filter; + return this; + } + + /** Sets {@code filter[tags]}. */ + public Builder filterTags(String filterTags) { + this.filterTags = filterTags; + return this; + } + + /** Sets {@code filter[overdue]}. */ + public Builder filterOverdue(String filterOverdue) { + this.filterOverdue = filterOverdue; + return this; + } + + /** Sets {@code filter[project]}. */ + public Builder filterProject(String filterProject) { + this.filterProject = filterProject; + return this; + } + + /** Sets {@code filter[type]}. */ + public Builder filterType(MessageType filterType) { + this.filterType = filterType; + return this; + } + + /** Sets {@code filter[status]}. */ + public Builder filterStatus(MessageStatus filterStatus) { + this.filterStatus = filterStatus; + return this; + } + + /** Sets {@code filter[delivery_mode]}. */ + public Builder filterDeliveryMode(DeliveryMode filterDeliveryMode) { + this.filterDeliveryMode = filterDeliveryMode; + return this; + } + + /** Sets {@code filter[route_id]}. */ + public Builder filterRouteId(String filterRouteId) { + this.filterRouteId = filterRouteId; + return this; + } + + /** Sets {@code filter[domain_id]}. */ + public Builder filterDomainId(String filterDomainId) { + this.filterDomainId = filterDomainId; + return this; + } + + /** Sets {@code filter[tag]}. */ + public Builder filterTag(String filterTag) { + this.filterTag = filterTag; + return this; + } + + /** Sets {@code filter[from_date]}. */ + public Builder filterFromDate(String filterFromDate) { + this.filterFromDate = filterFromDate; + return this; + } + + /** Sets {@code filter[to_date]}. */ + public Builder filterToDate(String filterToDate) { + this.filterToDate = filterToDate; + return this; + } + + /** Returns the {@link ListMessagesQuery}. */ + public ListMessagesQuery build() { + return new ListMessagesQuery(sort, filterSearch, filterTags0Name, filterTags0Value, filterFromEmail, filterSubject, pageSize, pageCursor, filter, filterTags, filterOverdue, filterProject, filterType, filterStatus, filterDeliveryMode, filterRouteId, filterDomainId, filterTag, filterFromDate, filterToDate); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java b/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java new file mode 100644 index 0000000..6a2b284 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java @@ -0,0 +1,58 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param tags Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ListMessagesQueryFilter( + @JsonProperty("tags") List tags +) { + /** Copies lists and maps into unmodifiable collections. */ + public ListMessagesQueryFilter { + tags = Copies.list(tags); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListMessagesQueryFilter. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.tags = tags; + return builder; + } + + /** Builds a {@link ListMessagesQueryFilter}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List tags; + + private Builder() { + } + + /** Sets {@code tags}. */ + public Builder tags(List tags) { + this.tags = tags; + return this; + } + + /** Returns the {@link ListMessagesQueryFilter}. */ + public ListMessagesQueryFilter build() { + return new ListMessagesQueryFilter(tags); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java b/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java new file mode 100644 index 0000000..e61232a --- /dev/null +++ b/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Optional: null omits it. + * @param value Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ListMessagesQueryFilterTagsItem( + @JsonProperty("name") String name, + @JsonProperty("value") String value +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListMessagesQueryFilterTagsItem. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.value = value; + return builder; + } + + /** Builds a {@link ListMessagesQueryFilterTagsItem}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private String value; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code value}. */ + public Builder value(String value) { + this.value = value; + return this; + } + + /** Returns the {@link ListMessagesQueryFilterTagsItem}. */ + public ListMessagesQueryFilterTagsItem build() { + return new ListMessagesQueryFilterTagsItem(name, value); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java b/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java new file mode 100644 index 0000000..d6bb534 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java @@ -0,0 +1,130 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListMessagesQuerySortItem { + /** {@code "type"} */ + public static final ListMessagesQuerySortItem TYPE = new ListMessagesQuerySortItem("type"); + + /** {@code "-type"} */ + public static final ListMessagesQuerySortItem TYPE_DESC = new ListMessagesQuerySortItem("-type"); + + /** {@code "status"} */ + public static final ListMessagesQuerySortItem STATUS = new ListMessagesQuerySortItem("status"); + + /** {@code "-status"} */ + public static final ListMessagesQuerySortItem STATUS_DESC = new ListMessagesQuerySortItem("-status"); + + /** {@code "from_email"} */ + public static final ListMessagesQuerySortItem FROM_EMAIL = new ListMessagesQuerySortItem("from_email"); + + /** {@code "-from_email"} */ + public static final ListMessagesQuerySortItem FROM_EMAIL_DESC = new ListMessagesQuerySortItem("-from_email"); + + /** {@code "subject"} */ + public static final ListMessagesQuerySortItem SUBJECT = new ListMessagesQuerySortItem("subject"); + + /** {@code "-subject"} */ + public static final ListMessagesQuerySortItem SUBJECT_DESC = new ListMessagesQuerySortItem("-subject"); + + /** {@code "created_at"} */ + public static final ListMessagesQuerySortItem CREATED_AT = new ListMessagesQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListMessagesQuerySortItem CREATED_AT_DESC = new ListMessagesQuerySortItem("-created_at"); + + /** {@code "status_changed_at"} */ + public static final ListMessagesQuerySortItem STATUS_CHANGED_AT = new ListMessagesQuerySortItem("status_changed_at"); + + /** {@code "-status_changed_at"} */ + public static final ListMessagesQuerySortItem STATUS_CHANGED_AT_DESC = new ListMessagesQuerySortItem("-status_changed_at"); + + /** {@code "scheduled_at"} */ + public static final ListMessagesQuerySortItem SCHEDULED_AT = new ListMessagesQuerySortItem("scheduled_at"); + + /** {@code "-scheduled_at"} */ + public static final ListMessagesQuerySortItem SCHEDULED_AT_DESC = new ListMessagesQuerySortItem("-scheduled_at"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TYPE.value, TYPE); + known.put(TYPE_DESC.value, TYPE_DESC); + known.put(STATUS.value, STATUS); + known.put(STATUS_DESC.value, STATUS_DESC); + known.put(FROM_EMAIL.value, FROM_EMAIL); + known.put(FROM_EMAIL_DESC.value, FROM_EMAIL_DESC); + known.put(SUBJECT.value, SUBJECT); + known.put(SUBJECT_DESC.value, SUBJECT_DESC); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + known.put(STATUS_CHANGED_AT.value, STATUS_CHANGED_AT); + known.put(STATUS_CHANGED_AT_DESC.value, STATUS_CHANGED_AT_DESC); + known.put(SCHEDULED_AT.value, SCHEDULED_AT); + known.put(SCHEDULED_AT_DESC.value, SCHEDULED_AT_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListMessagesQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListMessagesQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListMessagesQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListMessagesQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListMessagesQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListProjectsQuery.java b/src/main/java/co/lettermint/types/ListProjectsQuery.java new file mode 100644 index 0000000..23817a5 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListProjectsQuery.java @@ -0,0 +1,103 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /projects (listProjects). + * + * @param pageSize The number of results that will be returned per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor The cursor to start the pagination from. Optional: null omits it. Sent as page[cursor]. + * @param filterSearch Optional: null omits it. Sent as filter[search]. + * @param sort Optional: null omits it. Sent as sort. + */ +public record ListProjectsQuery( + Long pageSize, + String pageCursor, + String filterSearch, + List sort +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListProjectsQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + parameters.put("filter[search]", filterSearch); + parameters.put("sort", sort); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListProjectsQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + builder.filterSearch = filterSearch; + builder.sort = sort; + return builder; + } + + /** Builds a {@link ListProjectsQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String pageCursor; + private String filterSearch; + private List sort; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Sets {@code filter[search]}. */ + public Builder filterSearch(String filterSearch) { + this.filterSearch = filterSearch; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Returns the {@link ListProjectsQuery}. */ + public ListProjectsQuery build() { + return new ListProjectsQuery(pageSize, pageCursor, filterSearch, sort); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java b/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java new file mode 100644 index 0000000..32cd815 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListProjectsQuerySortItem { + /** {@code "name"} */ + public static final ListProjectsQuerySortItem NAME = new ListProjectsQuerySortItem("name"); + + /** {@code "-name"} */ + public static final ListProjectsQuerySortItem NAME_DESC = new ListProjectsQuerySortItem("-name"); + + /** {@code "created_at"} */ + public static final ListProjectsQuerySortItem CREATED_AT = new ListProjectsQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListProjectsQuerySortItem CREATED_AT_DESC = new ListProjectsQuerySortItem("-created_at"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(NAME.value, NAME); + known.put(NAME_DESC.value, NAME_DESC); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListProjectsQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListProjectsQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListProjectsQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListProjectsQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListProjectsQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListRoutesQuery.java b/src/main/java/co/lettermint/types/ListRoutesQuery.java new file mode 100644 index 0000000..25fb890 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListRoutesQuery.java @@ -0,0 +1,125 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /projects/{projectId}/routes (listRoutes). + * + * @param pageSize The number of results that will be returned per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor The cursor to start the pagination from. Optional: null omits it. Sent as page[cursor]. + * @param sort Optional: null omits it. Sent as sort. + * @param filterRouteType Optional: null omits it. Sent as filter[route_type]. + * @param filterIsDefault Optional: null omits it. Sent as filter[is_default]. + * @param filterSearch Search by name or slug. Optional: null omits it. Sent as filter[search]. + */ +public record ListRoutesQuery( + Long pageSize, + String pageCursor, + List sort, + RouteType filterRouteType, + Boolean filterIsDefault, + String filterSearch +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListRoutesQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + parameters.put("sort", sort); + parameters.put("filter[route_type]", filterRouteType); + parameters.put("filter[is_default]", filterIsDefault); + parameters.put("filter[search]", filterSearch); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListRoutesQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + builder.sort = sort; + builder.filterRouteType = filterRouteType; + builder.filterIsDefault = filterIsDefault; + builder.filterSearch = filterSearch; + return builder; + } + + /** Builds a {@link ListRoutesQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String pageCursor; + private List sort; + private RouteType filterRouteType; + private Boolean filterIsDefault; + private String filterSearch; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Sets {@code filter[route_type]}. */ + public Builder filterRouteType(RouteType filterRouteType) { + this.filterRouteType = filterRouteType; + return this; + } + + /** Sets {@code filter[is_default]}. */ + public Builder filterIsDefault(Boolean filterIsDefault) { + this.filterIsDefault = filterIsDefault; + return this; + } + + /** Sets {@code filter[search]}. */ + public Builder filterSearch(String filterSearch) { + this.filterSearch = filterSearch; + return this; + } + + /** Returns the {@link ListRoutesQuery}. */ + public ListRoutesQuery build() { + return new ListRoutesQuery(pageSize, pageCursor, sort, filterRouteType, filterIsDefault, filterSearch); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java b/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java new file mode 100644 index 0000000..7f4184b --- /dev/null +++ b/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListRoutesQuerySortItem { + /** {@code "name"} */ + public static final ListRoutesQuerySortItem NAME = new ListRoutesQuerySortItem("name"); + + /** {@code "-name"} */ + public static final ListRoutesQuerySortItem NAME_DESC = new ListRoutesQuerySortItem("-name"); + + /** {@code "slug"} */ + public static final ListRoutesQuerySortItem SLUG = new ListRoutesQuerySortItem("slug"); + + /** {@code "-slug"} */ + public static final ListRoutesQuerySortItem SLUG_DESC = new ListRoutesQuerySortItem("-slug"); + + /** {@code "created_at"} */ + public static final ListRoutesQuerySortItem CREATED_AT = new ListRoutesQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListRoutesQuerySortItem CREATED_AT_DESC = new ListRoutesQuerySortItem("-created_at"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(NAME.value, NAME); + known.put(NAME_DESC.value, NAME_DESC); + known.put(SLUG.value, SLUG); + known.put(SLUG_DESC.value, SLUG_DESC); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListRoutesQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListRoutesQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListRoutesQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListRoutesQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListRoutesQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListSuppressionsQuery.java b/src/main/java/co/lettermint/types/ListSuppressionsQuery.java new file mode 100644 index 0000000..34d0baf --- /dev/null +++ b/src/main/java/co/lettermint/types/ListSuppressionsQuery.java @@ -0,0 +1,169 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /suppressions (listSuppressions). + * + * @param pageSize The number of results that will be returned per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor The cursor to start the pagination from. Optional: null omits it. Sent as page[cursor]. + * @param sort Optional: null omits it. Sent as sort. + * @param filterScope Filter by scope (team, project, route). Optional: null omits it. Sent as filter[scope]. + * @param filterRouteId Filter by route ID. Optional: null omits it. Sent as filter[route_id]. + * @param filterProjectId Filter by project ID. Optional: null omits it. Sent as filter[project_id]. + * @param filterValue Search by email/domain value (partial match). Optional: null omits it. Sent as filter[value]. + * @param filterReason Optional: null omits it. Sent as filter[reason]. + * @param filterStartDate Filter suppressions created or updated on or after this ISO 8601 date or datetime. Optional: null omits it. Sent as filter[startDate]. + * @param filterEndDate Filter suppressions created or updated on or before this ISO 8601 date or datetime. Optional: null omits it. Sent as filter[endDate]. + */ +public record ListSuppressionsQuery( + Long pageSize, + String pageCursor, + List sort, + String filterScope, + String filterRouteId, + String filterProjectId, + String filterValue, + SuppressionReason filterReason, + String filterStartDate, + String filterEndDate +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListSuppressionsQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + parameters.put("sort", sort); + parameters.put("filter[scope]", filterScope); + parameters.put("filter[route_id]", filterRouteId); + parameters.put("filter[project_id]", filterProjectId); + parameters.put("filter[value]", filterValue); + parameters.put("filter[reason]", filterReason); + parameters.put("filter[startDate]", filterStartDate); + parameters.put("filter[endDate]", filterEndDate); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListSuppressionsQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + builder.sort = sort; + builder.filterScope = filterScope; + builder.filterRouteId = filterRouteId; + builder.filterProjectId = filterProjectId; + builder.filterValue = filterValue; + builder.filterReason = filterReason; + builder.filterStartDate = filterStartDate; + builder.filterEndDate = filterEndDate; + return builder; + } + + /** Builds a {@link ListSuppressionsQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String pageCursor; + private List sort; + private String filterScope; + private String filterRouteId; + private String filterProjectId; + private String filterValue; + private SuppressionReason filterReason; + private String filterStartDate; + private String filterEndDate; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Sets {@code filter[scope]}. */ + public Builder filterScope(String filterScope) { + this.filterScope = filterScope; + return this; + } + + /** Sets {@code filter[route_id]}. */ + public Builder filterRouteId(String filterRouteId) { + this.filterRouteId = filterRouteId; + return this; + } + + /** Sets {@code filter[project_id]}. */ + public Builder filterProjectId(String filterProjectId) { + this.filterProjectId = filterProjectId; + return this; + } + + /** Sets {@code filter[value]}. */ + public Builder filterValue(String filterValue) { + this.filterValue = filterValue; + return this; + } + + /** Sets {@code filter[reason]}. */ + public Builder filterReason(SuppressionReason filterReason) { + this.filterReason = filterReason; + return this; + } + + /** Sets {@code filter[startDate]}. */ + public Builder filterStartDate(String filterStartDate) { + this.filterStartDate = filterStartDate; + return this; + } + + /** Sets {@code filter[endDate]}. */ + public Builder filterEndDate(String filterEndDate) { + this.filterEndDate = filterEndDate; + return this; + } + + /** Returns the {@link ListSuppressionsQuery}. */ + public ListSuppressionsQuery build() { + return new ListSuppressionsQuery(pageSize, pageCursor, sort, filterScope, filterRouteId, filterProjectId, filterValue, filterReason, filterStartDate, filterEndDate); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java b/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java new file mode 100644 index 0000000..1d143c0 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListSuppressionsQuerySortItem { + /** {@code "value"} */ + public static final ListSuppressionsQuerySortItem VALUE = new ListSuppressionsQuerySortItem("value"); + + /** {@code "-value"} */ + public static final ListSuppressionsQuerySortItem VALUE_DESC = new ListSuppressionsQuerySortItem("-value"); + + /** {@code "created_at"} */ + public static final ListSuppressionsQuerySortItem CREATED_AT = new ListSuppressionsQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListSuppressionsQuerySortItem CREATED_AT_DESC = new ListSuppressionsQuerySortItem("-created_at"); + + /** {@code "reason"} */ + public static final ListSuppressionsQuerySortItem REASON = new ListSuppressionsQuerySortItem("reason"); + + /** {@code "-reason"} */ + public static final ListSuppressionsQuerySortItem REASON_DESC = new ListSuppressionsQuerySortItem("-reason"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(VALUE.value, VALUE); + known.put(VALUE_DESC.value, VALUE_DESC); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + known.put(REASON.value, REASON); + known.put(REASON_DESC.value, REASON_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListSuppressionsQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListSuppressionsQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListSuppressionsQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListSuppressionsQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListSuppressionsQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListTeamMembersQuery.java b/src/main/java/co/lettermint/types/ListTeamMembersQuery.java new file mode 100644 index 0000000..cd118ee --- /dev/null +++ b/src/main/java/co/lettermint/types/ListTeamMembersQuery.java @@ -0,0 +1,76 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Query parameters of GET /team/members (listTeamMembers). + * + * @param pageSize The number of results that will be returned per page. Optional: null omits it. Sent as page[size]. + * @param pageCursor The cursor to start the pagination from. Optional: null omits it. Sent as page[cursor]. + */ +public record ListTeamMembersQuery( + Long pageSize, + String pageCursor +) implements QueryParameters { + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("page[cursor]", pageCursor); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListTeamMembersQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.pageCursor = pageCursor; + return builder; + } + + /** Builds a {@link ListTeamMembersQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String pageCursor; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[cursor]}. */ + public Builder pageCursor(String pageCursor) { + this.pageCursor = pageCursor; + return this; + } + + /** Returns the {@link ListTeamMembersQuery}. */ + public ListTeamMembersQuery build() { + return new ListTeamMembersQuery(pageSize, pageCursor); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java new file mode 100644 index 0000000..22ab70d --- /dev/null +++ b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java @@ -0,0 +1,119 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /webhooks/{webhookId}/deliveries (listWebhookDeliveries). + * + * @param cursor Cursor for the next or previous page. Optional: null omits it. Sent as cursor. + * @param sort Optional: null omits it. Sent as sort. + * @param filterStatus Filter by delivery status. Optional: null omits it. Sent as filter[status]. + * @param filterEventType Filter by event type. Optional: null omits it. Sent as filter[event_type]. + * @param filterFromDate Filter deliveries from this date (Y-m-d format). Optional: null omits it. Sent as filter[from_date]. + * @param filterToDate Filter deliveries to this date (Y-m-d format). Optional: null omits it. Sent as filter[to_date]. + */ +public record ListWebhookDeliveriesQuery( + String cursor, + List sort, + WebhookDeliveryStatus filterStatus, + String filterEventType, + String filterFromDate, + String filterToDate +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListWebhookDeliveriesQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("cursor", cursor); + parameters.put("sort", sort); + parameters.put("filter[status]", filterStatus); + parameters.put("filter[event_type]", filterEventType); + parameters.put("filter[from_date]", filterFromDate); + parameters.put("filter[to_date]", filterToDate); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListWebhookDeliveriesQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.cursor = cursor; + builder.sort = sort; + builder.filterStatus = filterStatus; + builder.filterEventType = filterEventType; + builder.filterFromDate = filterFromDate; + builder.filterToDate = filterToDate; + return builder; + } + + /** Builds a {@link ListWebhookDeliveriesQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String cursor; + private List sort; + private WebhookDeliveryStatus filterStatus; + private String filterEventType; + private String filterFromDate; + private String filterToDate; + + private Builder() { + } + + /** Sets {@code cursor}. */ + public Builder cursor(String cursor) { + this.cursor = cursor; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Sets {@code filter[status]}. */ + public Builder filterStatus(WebhookDeliveryStatus filterStatus) { + this.filterStatus = filterStatus; + return this; + } + + /** Sets {@code filter[event_type]}. */ + public Builder filterEventType(String filterEventType) { + this.filterEventType = filterEventType; + return this; + } + + /** Sets {@code filter[from_date]}. */ + public Builder filterFromDate(String filterFromDate) { + this.filterFromDate = filterFromDate; + return this; + } + + /** Sets {@code filter[to_date]}. */ + public Builder filterToDate(String filterToDate) { + this.filterToDate = filterToDate; + return this; + } + + /** Returns the {@link ListWebhookDeliveriesQuery}. */ + public ListWebhookDeliveriesQuery build() { + return new ListWebhookDeliveriesQuery(cursor, sort, filterStatus, filterEventType, filterFromDate, filterToDate); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java new file mode 100644 index 0000000..89b251e --- /dev/null +++ b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListWebhookDeliveriesQuerySortItem { + /** {@code "created_at"} */ + public static final ListWebhookDeliveriesQuerySortItem CREATED_AT = new ListWebhookDeliveriesQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListWebhookDeliveriesQuerySortItem CREATED_AT_DESC = new ListWebhookDeliveriesQuerySortItem("-created_at"); + + /** {@code "attempt_number"} */ + public static final ListWebhookDeliveriesQuerySortItem ATTEMPT_NUMBER = new ListWebhookDeliveriesQuerySortItem("attempt_number"); + + /** {@code "-attempt_number"} */ + public static final ListWebhookDeliveriesQuerySortItem ATTEMPT_NUMBER_DESC = new ListWebhookDeliveriesQuerySortItem("-attempt_number"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + known.put(ATTEMPT_NUMBER.value, ATTEMPT_NUMBER); + known.put(ATTEMPT_NUMBER_DESC.value, ATTEMPT_NUMBER_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListWebhookDeliveriesQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListWebhookDeliveriesQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListWebhookDeliveriesQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListWebhookDeliveriesQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListWebhookDeliveriesQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ListWebhooksQuery.java b/src/main/java/co/lettermint/types/ListWebhooksQuery.java new file mode 100644 index 0000000..7e17ad7 --- /dev/null +++ b/src/main/java/co/lettermint/types/ListWebhooksQuery.java @@ -0,0 +1,158 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Query parameters of GET /webhooks (listWebhooks). + * + * @param pageSize Optional: null omits it. Sent as page[size]. + * @param cursor Cursor for the next or previous page. Optional: null omits it. Sent as cursor. + * @param sort Optional: null omits it. Sent as sort. + * @param filterProject Filter by project ID. Optional: null omits it. Sent as filter[project]. + * @param filterEnabled Filter by enabled status. Optional: null omits it. Sent as filter[enabled]. + * @param filterEvent Filter by specific event type. Optional: null omits it. Sent as filter[event]. + * @param filterRouteId Filter by route ID. Optional: null omits it. Sent as filter[route_id]. + * @param filterScope Filter by webhook scope. Optional: null omits it. Sent as filter[scope]. + * @param filterSearch Search by webhook name or URL. Optional: null omits it. Sent as filter[search]. + */ +public record ListWebhooksQuery( + Long pageSize, + String cursor, + List sort, + String filterProject, + Boolean filterEnabled, + WebhookEvent filterEvent, + String filterRouteId, + WebhookScope filterScope, + String filterSearch +) implements QueryParameters { + /** Copies lists and maps into unmodifiable collections. */ + public ListWebhooksQuery { + sort = Copies.list(sort); + } + + /** The parameters by wire name, in the order of the specification. {@code null} values are left out when sent. */ + @Override + public Map toParameters() { + Map parameters = new LinkedHashMap<>(); + parameters.put("page[size]", pageSize); + parameters.put("cursor", cursor); + parameters.put("sort", sort); + parameters.put("filter[project]", filterProject); + parameters.put("filter[enabled]", filterEnabled); + parameters.put("filter[event]", filterEvent); + parameters.put("filter[route_id]", filterRouteId); + parameters.put("filter[scope]", filterScope); + parameters.put("filter[search]", filterSearch); + return parameters; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ListWebhooksQuery. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.pageSize = pageSize; + builder.cursor = cursor; + builder.sort = sort; + builder.filterProject = filterProject; + builder.filterEnabled = filterEnabled; + builder.filterEvent = filterEvent; + builder.filterRouteId = filterRouteId; + builder.filterScope = filterScope; + builder.filterSearch = filterSearch; + return builder; + } + + /** Builds a {@link ListWebhooksQuery}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long pageSize; + private String cursor; + private List sort; + private String filterProject; + private Boolean filterEnabled; + private WebhookEvent filterEvent; + private String filterRouteId; + private WebhookScope filterScope; + private String filterSearch; + + private Builder() { + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(Long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code page[size]}. */ + public Builder pageSize(long pageSize) { + this.pageSize = pageSize; + return this; + } + + /** Sets {@code cursor}. */ + public Builder cursor(String cursor) { + this.cursor = cursor; + return this; + } + + /** Sets {@code sort}. */ + public Builder sort(List sort) { + this.sort = sort; + return this; + } + + /** Sets {@code filter[project]}. */ + public Builder filterProject(String filterProject) { + this.filterProject = filterProject; + return this; + } + + /** Sets {@code filter[enabled]}. */ + public Builder filterEnabled(Boolean filterEnabled) { + this.filterEnabled = filterEnabled; + return this; + } + + /** Sets {@code filter[event]}. */ + public Builder filterEvent(WebhookEvent filterEvent) { + this.filterEvent = filterEvent; + return this; + } + + /** Sets {@code filter[route_id]}. */ + public Builder filterRouteId(String filterRouteId) { + this.filterRouteId = filterRouteId; + return this; + } + + /** Sets {@code filter[scope]}. */ + public Builder filterScope(WebhookScope filterScope) { + this.filterScope = filterScope; + return this; + } + + /** Sets {@code filter[search]}. */ + public Builder filterSearch(String filterSearch) { + this.filterSearch = filterSearch; + return this; + } + + /** Returns the {@link ListWebhooksQuery}. */ + public ListWebhooksQuery build() { + return new ListWebhooksQuery(pageSize, cursor, sort, filterProject, filterEnabled, filterEvent, filterRouteId, filterScope, filterSearch); + } + } +} diff --git a/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java b/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java new file mode 100644 index 0000000..dc10c1e --- /dev/null +++ b/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ListWebhooksQuerySortItem { + /** {@code "name"} */ + public static final ListWebhooksQuerySortItem NAME = new ListWebhooksQuerySortItem("name"); + + /** {@code "-name"} */ + public static final ListWebhooksQuerySortItem NAME_DESC = new ListWebhooksQuerySortItem("-name"); + + /** {@code "url"} */ + public static final ListWebhooksQuerySortItem URL = new ListWebhooksQuerySortItem("url"); + + /** {@code "-url"} */ + public static final ListWebhooksQuerySortItem URL_DESC = new ListWebhooksQuerySortItem("-url"); + + /** {@code "created_at"} */ + public static final ListWebhooksQuerySortItem CREATED_AT = new ListWebhooksQuerySortItem("created_at"); + + /** {@code "-created_at"} */ + public static final ListWebhooksQuerySortItem CREATED_AT_DESC = new ListWebhooksQuerySortItem("-created_at"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(NAME.value, NAME); + known.put(NAME_DESC.value, NAME_DESC); + known.put(URL.value, URL); + known.put(URL_DESC.value, URL_DESC); + known.put(CREATED_AT.value, CREATED_AT); + known.put(CREATED_AT_DESC.value, CREATED_AT_DESC); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ListWebhooksQuerySortItem(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ListWebhooksQuerySortItem of(String value) { + Objects.requireNonNull(value, "value"); + ListWebhooksQuerySortItem known = KNOWN.get(value); + return known != null ? known : new ListWebhooksQuerySortItem(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ListWebhooksQuerySortItem that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/MessageAttachmentData.java b/src/main/java/co/lettermint/types/MessageAttachmentData.java new file mode 100644 index 0000000..a1bb0c2 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageAttachmentData.java @@ -0,0 +1,88 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param size Always present. + * @param filename Always present. + * @param contentId Always present; may be null. + * @param contentType Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageAttachmentData( + @JsonProperty("size") Long size, + @JsonProperty("filename") String filename, + @JsonProperty("content_id") String contentId, + @JsonProperty("content_type") String contentType +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageAttachmentData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.size = size; + builder.filename = filename; + builder.contentId = contentId; + builder.contentType = contentType; + return builder; + } + + /** Builds a {@link MessageAttachmentData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long size; + private String filename; + private String contentId; + private String contentType; + + private Builder() { + } + + /** Sets {@code size}. */ + public Builder size(Long size) { + this.size = size; + return this; + } + + /** Sets {@code size}. */ + public Builder size(long size) { + this.size = size; + return this; + } + + /** Sets {@code filename}. */ + public Builder filename(String filename) { + this.filename = filename; + return this; + } + + /** Sets {@code content_id}. */ + public Builder contentId(String contentId) { + this.contentId = contentId; + return this; + } + + /** Sets {@code content_type}. */ + public Builder contentType(String contentType) { + this.contentType = contentType; + return this; + } + + /** Returns the {@link MessageAttachmentData}. */ + public MessageAttachmentData build() { + return new MessageAttachmentData(size, filename, contentId, contentType); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageAttachmentInput.java b/src/main/java/co/lettermint/types/MessageAttachmentInput.java new file mode 100644 index 0000000..ded5f3e --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageAttachmentInput.java @@ -0,0 +1,84 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A file attached to the message. + * + * @param filename Required. + * @param content Required. + * @param contentType The MIME type of the attachment. Supports parameters (e.g. text/calendar; method=REQUEST). If omitted, detected automatically from content or filename. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param contentId Content ID for inline attachments, referenced via cid: in HTML body. If no @ is present, @lm is appended automatically. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageAttachmentInput( + @JsonProperty("filename") String filename, + @JsonProperty("content") String content, + @JsonProperty("content_type") OptionalNullable contentType, + @JsonProperty("content_id") OptionalNullable contentId +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageAttachmentInput. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.filename = filename; + builder.content = content; + builder.contentType = contentType; + builder.contentId = contentId; + return builder; + } + + /** Builds a {@link MessageAttachmentInput}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String filename; + private String content; + private OptionalNullable contentType; + private OptionalNullable contentId; + + private Builder() { + } + + /** Sets {@code filename}. */ + public Builder filename(String filename) { + this.filename = filename; + return this; + } + + /** Sets {@code content}. */ + public Builder content(String content) { + this.content = content; + return this; + } + + /** Sets {@code content_type}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder contentType(String contentType) { + this.contentType = OptionalNullable.of(contentType); + return this; + } + + /** Sets {@code content_id}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder contentId(String contentId) { + this.contentId = OptionalNullable.of(contentId); + return this; + } + + /** Returns the {@link MessageAttachmentInput}. */ + public MessageAttachmentInput build() { + return new MessageAttachmentInput(filename, content, contentType, contentId); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageData.java b/src/main/java/co/lettermint/types/MessageData.java new file mode 100644 index 0000000..b920385 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageData.java @@ -0,0 +1,282 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +/** + * @param id Always present. + * @param type Always present. + * @param status Always present. + * @param deliveryMode Always present. + * @param sandboxResult Always present; may be null. + * @param statusChangedAt Always present; may be null. + * @param scheduledAt Always present; may be null. + * @param tag Always present; may be null. + * @param tags Always present. + * @param fromEmail Always present. + * @param fromName Always present; may be null. + * @param replyTo Always present; may be null. + * @param subject Always present; may be null. + * @param to Always present; may be null. + * @param cc Always present; may be null. + * @param bcc Always present; may be null. + * @param attachments Always present; may be null. + * @param metadata Always present; may be null. + * @param spamScore Overall spam assessment score. Scores below 5 are clean, 5 through 10 indicate potential spam, scores above 10 and below 15 are likely spam, and 15 or higher is definite spam. Null means no assessment is available. Available on plans with Spam Insights. Optional and nullable: null when absent or null. + * @param spamSymbols Detailed rules that contributed to the spam assessment. Available on plans with Spam Insights in individual-message responses. Optional: null when absent. + * @param routeId Always present. + * @param createdAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageData( + @JsonProperty("id") String id, + @JsonProperty("type") MessageType type, + @JsonProperty("status") MessageStatus status, + @JsonProperty("delivery_mode") DeliveryMode deliveryMode, + @JsonProperty("sandbox_result") SandboxResult sandboxResult, + @JsonProperty("status_changed_at") String statusChangedAt, + @JsonProperty("scheduled_at") String scheduledAt, + @JsonProperty("tag") String tag, + @JsonProperty("tags") List tags, + @JsonProperty("from_email") String fromEmail, + @JsonProperty("from_name") String fromName, + @JsonProperty("reply_to") List replyTo, + @JsonProperty("subject") String subject, + @JsonProperty("to") List to, + @JsonProperty("cc") List cc, + @JsonProperty("bcc") List bcc, + @JsonProperty("attachments") List attachments, + @JsonProperty("metadata") Map metadata, + @JsonProperty("spam_score") Double spamScore, + @JsonProperty("spam_symbols") List spamSymbols, + @JsonProperty("route_id") String routeId, + @JsonProperty("created_at") String createdAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public MessageData { + tags = Copies.list(tags); + replyTo = Copies.list(replyTo); + to = Copies.list(to); + cc = Copies.list(cc); + bcc = Copies.list(bcc); + attachments = Copies.list(attachments); + metadata = Copies.map(metadata); + spamSymbols = Copies.list(spamSymbols); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.type = type; + builder.status = status; + builder.deliveryMode = deliveryMode; + builder.sandboxResult = sandboxResult; + builder.statusChangedAt = statusChangedAt; + builder.scheduledAt = scheduledAt; + builder.tag = tag; + builder.tags = tags; + builder.fromEmail = fromEmail; + builder.fromName = fromName; + builder.replyTo = replyTo; + builder.subject = subject; + builder.to = to; + builder.cc = cc; + builder.bcc = bcc; + builder.attachments = attachments; + builder.metadata = metadata; + builder.spamScore = spamScore; + builder.spamSymbols = spamSymbols; + builder.routeId = routeId; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link MessageData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private MessageType type; + private MessageStatus status; + private DeliveryMode deliveryMode; + private SandboxResult sandboxResult; + private String statusChangedAt; + private String scheduledAt; + private String tag; + private List tags; + private String fromEmail; + private String fromName; + private List replyTo; + private String subject; + private List to; + private List cc; + private List bcc; + private List attachments; + private Map metadata; + private Double spamScore; + private List spamSymbols; + private String routeId; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code type}. */ + public Builder type(MessageType type) { + this.type = type; + return this; + } + + /** Sets {@code status}. */ + public Builder status(MessageStatus status) { + this.status = status; + return this; + } + + /** Sets {@code delivery_mode}. */ + public Builder deliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = deliveryMode; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Sets {@code status_changed_at}. */ + public Builder statusChangedAt(String statusChangedAt) { + this.statusChangedAt = statusChangedAt; + return this; + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Sets {@code tag}. */ + public Builder tag(String tag) { + this.tag = tag; + return this; + } + + /** Sets {@code tags}. */ + public Builder tags(List tags) { + this.tags = tags; + return this; + } + + /** Sets {@code from_email}. */ + public Builder fromEmail(String fromEmail) { + this.fromEmail = fromEmail; + return this; + } + + /** Sets {@code from_name}. */ + public Builder fromName(String fromName) { + this.fromName = fromName; + return this; + } + + /** Sets {@code reply_to}. */ + public Builder replyTo(List replyTo) { + this.replyTo = replyTo; + return this; + } + + /** Sets {@code subject}. */ + public Builder subject(String subject) { + this.subject = subject; + return this; + } + + /** Sets {@code to}. */ + public Builder to(List to) { + this.to = to; + return this; + } + + /** Sets {@code cc}. */ + public Builder cc(List cc) { + this.cc = cc; + return this; + } + + /** Sets {@code bcc}. */ + public Builder bcc(List bcc) { + this.bcc = bcc; + return this; + } + + /** Sets {@code attachments}. */ + public Builder attachments(List attachments) { + this.attachments = attachments; + return this; + } + + /** Sets {@code metadata}. */ + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + /** Sets {@code spam_score}. */ + public Builder spamScore(Double spamScore) { + this.spamScore = spamScore; + return this; + } + + /** Sets {@code spam_score}. */ + public Builder spamScore(double spamScore) { + this.spamScore = spamScore; + return this; + } + + /** Sets {@code spam_symbols}. */ + public Builder spamSymbols(List spamSymbols) { + this.spamSymbols = spamSymbols; + return this; + } + + /** Sets {@code route_id}. */ + public Builder routeId(String routeId) { + this.routeId = routeId; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link MessageData}. */ + public MessageData build() { + return new MessageData(id, type, status, deliveryMode, sandboxResult, statusChangedAt, scheduledAt, tag, tags, fromEmail, fromName, replyTo, subject, to, cc, bcc, attachments, metadata, spamScore, spamSymbols, routeId, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageEventData.java b/src/main/java/co/lettermint/types/MessageEventData.java new file mode 100644 index 0000000..5e61876 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageEventData.java @@ -0,0 +1,110 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +/** + * @param messageId Always present. + * @param event Always present. + * @param tag Always present; may be null. + * @param tags Always present. + * @param metadata Always present; may be null. + * @param timestamp Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageEventData( + @JsonProperty("message_id") String messageId, + @JsonProperty("event") MessageEventType event, + @JsonProperty("tag") String tag, + @JsonProperty("tags") List tags, + @JsonProperty("metadata") Map metadata, + @JsonProperty("timestamp") String timestamp +) { + /** Copies lists and maps into unmodifiable collections. */ + public MessageEventData { + tags = Copies.list(tags); + metadata = Copies.map(metadata); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageEventData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messageId = messageId; + builder.event = event; + builder.tag = tag; + builder.tags = tags; + builder.metadata = metadata; + builder.timestamp = timestamp; + return builder; + } + + /** Builds a {@link MessageEventData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String messageId; + private MessageEventType event; + private String tag; + private List tags; + private Map metadata; + private String timestamp; + + private Builder() { + } + + /** Sets {@code message_id}. */ + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** Sets {@code event}. */ + public Builder event(MessageEventType event) { + this.event = event; + return this; + } + + /** Sets {@code tag}. */ + public Builder tag(String tag) { + this.tag = tag; + return this; + } + + /** Sets {@code tags}. */ + public Builder tags(List tags) { + this.tags = tags; + return this; + } + + /** Sets {@code metadata}. */ + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + /** Sets {@code timestamp}. */ + public Builder timestamp(String timestamp) { + this.timestamp = timestamp; + return this; + } + + /** Returns the {@link MessageEventData}. */ + public MessageEventData build() { + return new MessageEventData(messageId, event, tag, tags, metadata, timestamp); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageEventType.java b/src/main/java/co/lettermint/types/MessageEventType.java new file mode 100644 index 0000000..c2a7750 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageEventType.java @@ -0,0 +1,170 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class MessageEventType { + /** {@code "scheduled"} */ + public static final MessageEventType SCHEDULED = new MessageEventType("scheduled"); + + /** {@code "rescheduled"} */ + public static final MessageEventType RESCHEDULED = new MessageEventType("rescheduled"); + + /** {@code "canceled"} */ + public static final MessageEventType CANCELED = new MessageEventType("canceled"); + + /** {@code "released"} */ + public static final MessageEventType RELEASED = new MessageEventType("released"); + + /** {@code "queued"} */ + public static final MessageEventType QUEUED = new MessageEventType("queued"); + + /** {@code "processed"} */ + public static final MessageEventType PROCESSED = new MessageEventType("processed"); + + /** {@code "suppressed"} */ + public static final MessageEventType SUPPRESSED = new MessageEventType("suppressed"); + + /** {@code "delivered"} */ + public static final MessageEventType DELIVERED = new MessageEventType("delivered"); + + /** {@code "auto_replied"} */ + public static final MessageEventType AUTO_REPLIED = new MessageEventType("auto_replied"); + + /** {@code "soft_bounced"} */ + public static final MessageEventType SOFT_BOUNCED = new MessageEventType("soft_bounced"); + + /** {@code "hard_bounced"} */ + public static final MessageEventType HARD_BOUNCED = new MessageEventType("hard_bounced"); + + /** {@code "spam_complaint"} */ + public static final MessageEventType SPAM_COMPLAINT = new MessageEventType("spam_complaint"); + + /** {@code "failed"} */ + public static final MessageEventType FAILED = new MessageEventType("failed"); + + /** {@code "blocked"} */ + public static final MessageEventType BLOCKED = new MessageEventType("blocked"); + + /** {@code "policy_rejected"} */ + public static final MessageEventType POLICY_REJECTED = new MessageEventType("policy_rejected"); + + /** {@code "unsubscribed"} */ + public static final MessageEventType UNSUBSCRIBED = new MessageEventType("unsubscribed"); + + /** {@code "opened"} */ + public static final MessageEventType OPENED = new MessageEventType("opened"); + + /** {@code "clicked"} */ + public static final MessageEventType CLICKED = new MessageEventType("clicked"); + + /** {@code "inbound_received"} */ + public static final MessageEventType INBOUND_RECEIVED = new MessageEventType("inbound_received"); + + /** {@code "inbound_queued"} */ + public static final MessageEventType INBOUND_QUEUED = new MessageEventType("inbound_queued"); + + /** {@code "inbound_spam_blocked"} */ + public static final MessageEventType INBOUND_SPAM_BLOCKED = new MessageEventType("inbound_spam_blocked"); + + /** {@code "inbound_released"} */ + public static final MessageEventType INBOUND_RELEASED = new MessageEventType("inbound_released"); + + /** {@code "inbound_processed"} */ + public static final MessageEventType INBOUND_PROCESSED = new MessageEventType("inbound_processed"); + + /** {@code "inbound_retry"} */ + public static final MessageEventType INBOUND_RETRY = new MessageEventType("inbound_retry"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(SCHEDULED.value, SCHEDULED); + known.put(RESCHEDULED.value, RESCHEDULED); + known.put(CANCELED.value, CANCELED); + known.put(RELEASED.value, RELEASED); + known.put(QUEUED.value, QUEUED); + known.put(PROCESSED.value, PROCESSED); + known.put(SUPPRESSED.value, SUPPRESSED); + known.put(DELIVERED.value, DELIVERED); + known.put(AUTO_REPLIED.value, AUTO_REPLIED); + known.put(SOFT_BOUNCED.value, SOFT_BOUNCED); + known.put(HARD_BOUNCED.value, HARD_BOUNCED); + known.put(SPAM_COMPLAINT.value, SPAM_COMPLAINT); + known.put(FAILED.value, FAILED); + known.put(BLOCKED.value, BLOCKED); + known.put(POLICY_REJECTED.value, POLICY_REJECTED); + known.put(UNSUBSCRIBED.value, UNSUBSCRIBED); + known.put(OPENED.value, OPENED); + known.put(CLICKED.value, CLICKED); + known.put(INBOUND_RECEIVED.value, INBOUND_RECEIVED); + known.put(INBOUND_QUEUED.value, INBOUND_QUEUED); + known.put(INBOUND_SPAM_BLOCKED.value, INBOUND_SPAM_BLOCKED); + known.put(INBOUND_RELEASED.value, INBOUND_RELEASED); + known.put(INBOUND_PROCESSED.value, INBOUND_PROCESSED); + known.put(INBOUND_RETRY.value, INBOUND_RETRY); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private MessageEventType(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static MessageEventType of(String value) { + Objects.requireNonNull(value, "value"); + MessageEventType known = KNOWN.get(value); + return known != null ? known : new MessageEventType(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof MessageEventType that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/MessageListData.java b/src/main/java/co/lettermint/types/MessageListData.java new file mode 100644 index 0000000..0478fe9 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageListData.java @@ -0,0 +1,238 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param type Always present. + * @param status Always present. + * @param deliveryMode Always present. + * @param sandboxResult Always present; may be null. + * @param scheduledAt Always present; may be null. + * @param spamScore Overall spam assessment score. Scores below 5 are clean, 5 through 10 indicate potential spam, scores above 10 and below 15 are likely spam, and 15 or higher is definite spam. Null means no assessment is available. Available on plans with Spam Insights. Optional and nullable: null when absent or null. + * @param fromEmail Always present. + * @param fromName Always present; may be null. + * @param subject Always present; may be null. + * @param to Always present; may be null. + * @param cc Always present; may be null. + * @param bcc Always present; may be null. + * @param replyTo Always present; may be null. + * @param tag Always present; may be null. + * @param tags Always present. + * @param statusChangedAt Always present; may be null. + * @param createdAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageListData( + @JsonProperty("id") String id, + @JsonProperty("type") MessageType type, + @JsonProperty("status") MessageStatus status, + @JsonProperty("delivery_mode") DeliveryMode deliveryMode, + @JsonProperty("sandbox_result") SandboxResult sandboxResult, + @JsonProperty("scheduled_at") String scheduledAt, + @JsonProperty("spam_score") Double spamScore, + @JsonProperty("from_email") String fromEmail, + @JsonProperty("from_name") String fromName, + @JsonProperty("subject") String subject, + @JsonProperty("to") List to, + @JsonProperty("cc") List cc, + @JsonProperty("bcc") List bcc, + @JsonProperty("reply_to") List replyTo, + @JsonProperty("tag") String tag, + @JsonProperty("tags") List tags, + @JsonProperty("status_changed_at") String statusChangedAt, + @JsonProperty("created_at") String createdAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public MessageListData { + to = Copies.list(to); + cc = Copies.list(cc); + bcc = Copies.list(bcc); + replyTo = Copies.list(replyTo); + tags = Copies.list(tags); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageListData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.type = type; + builder.status = status; + builder.deliveryMode = deliveryMode; + builder.sandboxResult = sandboxResult; + builder.scheduledAt = scheduledAt; + builder.spamScore = spamScore; + builder.fromEmail = fromEmail; + builder.fromName = fromName; + builder.subject = subject; + builder.to = to; + builder.cc = cc; + builder.bcc = bcc; + builder.replyTo = replyTo; + builder.tag = tag; + builder.tags = tags; + builder.statusChangedAt = statusChangedAt; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link MessageListData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private MessageType type; + private MessageStatus status; + private DeliveryMode deliveryMode; + private SandboxResult sandboxResult; + private String scheduledAt; + private Double spamScore; + private String fromEmail; + private String fromName; + private String subject; + private List to; + private List cc; + private List bcc; + private List replyTo; + private String tag; + private List tags; + private String statusChangedAt; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code type}. */ + public Builder type(MessageType type) { + this.type = type; + return this; + } + + /** Sets {@code status}. */ + public Builder status(MessageStatus status) { + this.status = status; + return this; + } + + /** Sets {@code delivery_mode}. */ + public Builder deliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = deliveryMode; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Sets {@code spam_score}. */ + public Builder spamScore(Double spamScore) { + this.spamScore = spamScore; + return this; + } + + /** Sets {@code spam_score}. */ + public Builder spamScore(double spamScore) { + this.spamScore = spamScore; + return this; + } + + /** Sets {@code from_email}. */ + public Builder fromEmail(String fromEmail) { + this.fromEmail = fromEmail; + return this; + } + + /** Sets {@code from_name}. */ + public Builder fromName(String fromName) { + this.fromName = fromName; + return this; + } + + /** Sets {@code subject}. */ + public Builder subject(String subject) { + this.subject = subject; + return this; + } + + /** Sets {@code to}. */ + public Builder to(List to) { + this.to = to; + return this; + } + + /** Sets {@code cc}. */ + public Builder cc(List cc) { + this.cc = cc; + return this; + } + + /** Sets {@code bcc}. */ + public Builder bcc(List bcc) { + this.bcc = bcc; + return this; + } + + /** Sets {@code reply_to}. */ + public Builder replyTo(List replyTo) { + this.replyTo = replyTo; + return this; + } + + /** Sets {@code tag}. */ + public Builder tag(String tag) { + this.tag = tag; + return this; + } + + /** Sets {@code tags}. */ + public Builder tags(List tags) { + this.tags = tags; + return this; + } + + /** Sets {@code status_changed_at}. */ + public Builder statusChangedAt(String statusChangedAt) { + this.statusChangedAt = statusChangedAt; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link MessageListData}. */ + public MessageListData build() { + return new MessageListData(id, type, status, deliveryMode, sandboxResult, scheduledAt, spamScore, fromEmail, fromName, subject, to, cc, bcc, replyTo, tag, tags, statusChangedAt, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageRecipientData.java b/src/main/java/co/lettermint/types/MessageRecipientData.java new file mode 100644 index 0000000..dd090bb --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageRecipientData.java @@ -0,0 +1,72 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param email Always present. + * @param name Always present; may be null. + * @param sandboxResult The simulated result for this recipient in a Sandbox project. Lettermint test addresses override the message result. Null for Live messages. Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageRecipientData( + @JsonProperty("email") String email, + @JsonProperty("name") String name, + @JsonProperty("sandbox_result") SandboxResult sandboxResult +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageRecipientData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.email = email; + builder.name = name; + builder.sandboxResult = sandboxResult; + return builder; + } + + /** Builds a {@link MessageRecipientData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String email; + private String name; + private SandboxResult sandboxResult; + + private Builder() { + } + + /** Sets {@code email}. */ + public Builder email(String email) { + this.email = email; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Returns the {@link MessageRecipientData}. */ + public MessageRecipientData build() { + return new MessageRecipientData(email, name, sandboxResult); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageResponse.java b/src/main/java/co/lettermint/types/MessageResponse.java new file mode 100644 index 0000000..817fa4a --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageResponse.java @@ -0,0 +1,54 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Confirmation that a request succeeded. + * + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageResponse( + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + return builder; + } + + /** Builds a {@link MessageResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link MessageResponse}. */ + public MessageResponse build() { + return new MessageResponse(message); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageStatsData.java b/src/main/java/co/lettermint/types/MessageStatsData.java new file mode 100644 index 0000000..e12ffea --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageStatsData.java @@ -0,0 +1,106 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param messagesTransactional Always present. + * @param messagesBroadcast Always present. + * @param messagesInbound Always present. + * @param deliverability Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageStatsData( + @JsonProperty("messages_transactional") Long messagesTransactional, + @JsonProperty("messages_broadcast") Long messagesBroadcast, + @JsonProperty("messages_inbound") Long messagesInbound, + @JsonProperty("deliverability") Double deliverability +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageStatsData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messagesTransactional = messagesTransactional; + builder.messagesBroadcast = messagesBroadcast; + builder.messagesInbound = messagesInbound; + builder.deliverability = deliverability; + return builder; + } + + /** Builds a {@link MessageStatsData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long messagesTransactional; + private Long messagesBroadcast; + private Long messagesInbound; + private Double deliverability; + + private Builder() { + } + + /** Sets {@code messages_transactional}. */ + public Builder messagesTransactional(Long messagesTransactional) { + this.messagesTransactional = messagesTransactional; + return this; + } + + /** Sets {@code messages_transactional}. */ + public Builder messagesTransactional(long messagesTransactional) { + this.messagesTransactional = messagesTransactional; + return this; + } + + /** Sets {@code messages_broadcast}. */ + public Builder messagesBroadcast(Long messagesBroadcast) { + this.messagesBroadcast = messagesBroadcast; + return this; + } + + /** Sets {@code messages_broadcast}. */ + public Builder messagesBroadcast(long messagesBroadcast) { + this.messagesBroadcast = messagesBroadcast; + return this; + } + + /** Sets {@code messages_inbound}. */ + public Builder messagesInbound(Long messagesInbound) { + this.messagesInbound = messagesInbound; + return this; + } + + /** Sets {@code messages_inbound}. */ + public Builder messagesInbound(long messagesInbound) { + this.messagesInbound = messagesInbound; + return this; + } + + /** Sets {@code deliverability}. */ + public Builder deliverability(Double deliverability) { + this.deliverability = deliverability; + return this; + } + + /** Sets {@code deliverability}. */ + public Builder deliverability(double deliverability) { + this.deliverability = deliverability; + return this; + } + + /** Returns the {@link MessageStatsData}. */ + public MessageStatsData build() { + return new MessageStatsData(messagesTransactional, messagesBroadcast, messagesInbound, deliverability); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageStatus.java b/src/main/java/co/lettermint/types/MessageStatus.java new file mode 100644 index 0000000..a907a80 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageStatus.java @@ -0,0 +1,142 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class MessageStatus { + /** {@code "scheduled"} */ + public static final MessageStatus SCHEDULED = new MessageStatus("scheduled"); + + /** {@code "pending"} */ + public static final MessageStatus PENDING = new MessageStatus("pending"); + + /** {@code "queued"} */ + public static final MessageStatus QUEUED = new MessageStatus("queued"); + + /** {@code "quarantined"} */ + public static final MessageStatus QUARANTINED = new MessageStatus("quarantined"); + + /** {@code "suppressed"} */ + public static final MessageStatus SUPPRESSED = new MessageStatus("suppressed"); + + /** {@code "processed"} */ + public static final MessageStatus PROCESSED = new MessageStatus("processed"); + + /** {@code "delivered"} */ + public static final MessageStatus DELIVERED = new MessageStatus("delivered"); + + /** {@code "opened"} */ + public static final MessageStatus OPENED = new MessageStatus("opened"); + + /** {@code "clicked"} */ + public static final MessageStatus CLICKED = new MessageStatus("clicked"); + + /** {@code "soft_bounced"} */ + public static final MessageStatus SOFT_BOUNCED = new MessageStatus("soft_bounced"); + + /** {@code "hard_bounced"} */ + public static final MessageStatus HARD_BOUNCED = new MessageStatus("hard_bounced"); + + /** {@code "spam_complaint"} */ + public static final MessageStatus SPAM_COMPLAINT = new MessageStatus("spam_complaint"); + + /** {@code "failed"} */ + public static final MessageStatus FAILED = new MessageStatus("failed"); + + /** {@code "blocked"} */ + public static final MessageStatus BLOCKED = new MessageStatus("blocked"); + + /** {@code "policy_rejected"} */ + public static final MessageStatus POLICY_REJECTED = new MessageStatus("policy_rejected"); + + /** {@code "unsubscribed"} */ + public static final MessageStatus UNSUBSCRIBED = new MessageStatus("unsubscribed"); + + /** {@code "canceled"} */ + public static final MessageStatus CANCELED = new MessageStatus("canceled"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(SCHEDULED.value, SCHEDULED); + known.put(PENDING.value, PENDING); + known.put(QUEUED.value, QUEUED); + known.put(QUARANTINED.value, QUARANTINED); + known.put(SUPPRESSED.value, SUPPRESSED); + known.put(PROCESSED.value, PROCESSED); + known.put(DELIVERED.value, DELIVERED); + known.put(OPENED.value, OPENED); + known.put(CLICKED.value, CLICKED); + known.put(SOFT_BOUNCED.value, SOFT_BOUNCED); + known.put(HARD_BOUNCED.value, HARD_BOUNCED); + known.put(SPAM_COMPLAINT.value, SPAM_COMPLAINT); + known.put(FAILED.value, FAILED); + known.put(BLOCKED.value, BLOCKED); + known.put(POLICY_REJECTED.value, POLICY_REJECTED); + known.put(UNSUBSCRIBED.value, UNSUBSCRIBED); + known.put(CANCELED.value, CANCELED); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private MessageStatus(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static MessageStatus of(String value) { + Objects.requireNonNull(value, "value"); + MessageStatus known = KNOWN.get(value); + return known != null ? known : new MessageStatus(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof MessageStatus that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/MessageTag.java b/src/main/java/co/lettermint/types/MessageTag.java new file mode 100644 index 0000000..56c840b --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageTag.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Always present. + * @param value Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageTag( + @JsonProperty("name") String name, + @JsonProperty("value") String value +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageTag. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.value = value; + return builder; + } + + /** Builds a {@link MessageTag}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private String value; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code value}. */ + public Builder value(String value) { + this.value = value; + return this; + } + + /** Returns the {@link MessageTag}. */ + public MessageTag build() { + return new MessageTag(name, value); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageTagInput.java b/src/main/java/co/lettermint/types/MessageTagInput.java new file mode 100644 index 0000000..1375430 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageTagInput.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A reusable exact-match tag with a name and a value. + * + * @param name Required. + * @param value Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record MessageTagInput( + @JsonProperty("name") String name, + @JsonProperty("value") String value +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this MessageTagInput. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.value = value; + return builder; + } + + /** Builds a {@link MessageTagInput}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private String value; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code value}. */ + public Builder value(String value) { + this.value = value; + return this; + } + + /** Returns the {@link MessageTagInput}. */ + public MessageTagInput build() { + return new MessageTagInput(name, value); + } + } +} diff --git a/src/main/java/co/lettermint/types/MessageType.java b/src/main/java/co/lettermint/types/MessageType.java new file mode 100644 index 0000000..c93f195 --- /dev/null +++ b/src/main/java/co/lettermint/types/MessageType.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class MessageType { + /** {@code "inbound"} */ + public static final MessageType INBOUND = new MessageType("inbound"); + + /** {@code "outbound"} */ + public static final MessageType OUTBOUND = new MessageType("outbound"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(INBOUND.value, INBOUND); + known.put(OUTBOUND.value, OUTBOUND); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private MessageType(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static MessageType of(String value) { + Objects.requireNonNull(value, "value"); + MessageType known = KNOWN.get(value); + return known != null ? known : new MessageType(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof MessageType that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/Operations.java b/src/main/java/co/lettermint/types/Operations.java new file mode 100644 index 0000000..a3f5625 --- /dev/null +++ b/src/main/java/co/lettermint/types/Operations.java @@ -0,0 +1,1670 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.core.type.TypeReference; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Every operation of the Sending and Team APIs. Data, not a client: the SDK reads paths, auth surfaces and response types from it. + * + * ALL is keyed by <METHOD> <path>. + */ +public final class Operations { + private Operations() { + } + + /** Which API token an operation accepts: a sending token, a team token, or either. */ + public enum AuthSurface { + SENDING, + TEAM, + EITHER + } + + /** How the success body is read. */ + public enum ResponseKind { + /** A JSON body, decoded into {@link Operation#responseType()}. */ + JSON, + /** A text body, returned as a string. */ + TEXT, + /** No body. */ + EMPTY + } + + /** + * Cursor pagination of a list operation. + * + * @param items the item type name + * @param cursorParam the query parameter that takes {@code next_cursor} + * @param sizeParam the page size query parameter, or null + */ + public record Pagination(String items, String cursorParam, String sizeParam) { + } + + /** + * One operation. + * + * @param key {@code } + * @param operationId the operationId of the specification + * @param method the HTTP method + * @param path the path below the base URL, with {@code {name}} placeholders + * @param auth the tokens the operation accepts + * @param surfaces the API surfaces that document it + * @param pathParams the path parameter names + * @param query the query type name, or null + * @param headers the header parameters (credentials excluded) + * @param request the request body type, or null + * @param requestContentType the request content type, or null + * @param requestRequired whether the request body is required + * @param responseStatus the success statuses + * @param responseContentType the success content type, or null when it varies or there is no body + * @param responseKind how the success body is read + * @param responseType the Java type of the success body + * @param errors error statuses with the type names their body may have (empty: no body) + * @param pagination cursor pagination, or null + * @param deprecated whether the API deprecates the operation + * @param the Java type of the success body + */ + public record Operation( + String key, String operationId, String method, String path, AuthSurface auth, List surfaces, + List pathParams, String query, List headers, String request, String requestContentType, + boolean requestRequired, List responseStatus, String responseContentType, ResponseKind responseKind, + TypeReference responseType, Map> errors, Pagination pagination, boolean deprecated) { + } + + /** + * Delete a domain + * + * DELETE /domains/{domainId} (deleteDomain) + */ + public static final Operation DELETE_DOMAIN = new Operation<>( + "DELETE /domains/{domainId}", + "deleteDomain", + "DELETE", + "/domains/{domainId}", + AuthSurface.TEAM, + List.of("team"), + List.of("domainId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Delete a project + * + * DELETE /projects/{projectId} (deleteProject) + */ + public static final Operation DELETE_PROJECT = new Operation<>( + "DELETE /projects/{projectId}", + "deleteProject", + "DELETE", + "/projects/{projectId}", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Disable report forwarding + * + * DELETE /projects/{projectId}/report-forwarding (deleteReportForwarding) + */ + public static final Operation DELETE_REPORT_FORWARDING = new Operation<>( + "DELETE /projects/{projectId}/report-forwarding", + "deleteReportForwarding", + "DELETE", + "/projects/{projectId}/report-forwarding", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + null, + null, + false, + List.of(204), + null, + ResponseKind.EMPTY, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Delete a route + * + * DELETE /routes/{routeId} (deleteRoute) + */ + public static final Operation DELETE_ROUTE = new Operation<>( + "DELETE /routes/{routeId}", + "deleteRoute", + "DELETE", + "/routes/{routeId}", + AuthSurface.TEAM, + List.of("team"), + List.of("routeId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Remove email from suppression list + * + * DELETE /suppressions/{suppressionId} (deleteSuppression) + */ + public static final Operation DELETE_SUPPRESSION = new Operation<>( + "DELETE /suppressions/{suppressionId}", + "deleteSuppression", + "DELETE", + "/suppressions/{suppressionId}", + AuthSurface.TEAM, + List.of("team"), + List.of("suppressionId"), + null, + List.of(), + null, + null, + false, + List.of(200, 202), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Delete a webhook + * + * DELETE /webhooks/{webhookId} (deleteWebhook) + */ + public static final Operation DELETE_WEBHOOK = new Operation<>( + "DELETE /webhooks/{webhookId}", + "deleteWebhook", + "DELETE", + "/webhooks/{webhookId}", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * List blocked file types + * + * GET /blocked-file-types (listBlockedFileTypes) + */ + public static final Operation LIST_BLOCKED_FILE_TYPES = new Operation<>( + "GET /blocked-file-types", + "listBlockedFileTypes", + "GET", + "/blocked-file-types", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * List all domains for the team + * + * GET /domains (listDomains) + */ + public static final Operation> LIST_DOMAINS = new Operation<>( + "GET /domains", + "listDomains", + "GET", + "/domains", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "ListDomainsQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + new Pagination("DomainListData", "page[cursor]", "page[size]"), + false); + + /** + * Get domain details + * + * GET /domains/{domainId} (getDomain) + */ + public static final Operation GET_DOMAIN = new Operation<>( + "GET /domains/{domainId}", + "getDomain", + "GET", + "/domains/{domainId}", + AuthSurface.TEAM, + List.of("team"), + List.of("domainId"), + "GetDomainQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * List messages for the team + * + * GET /messages (listMessages) + */ + public static final Operation> LIST_MESSAGES = new Operation<>( + "GET /messages", + "listMessages", + "GET", + "/messages", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "ListMessagesQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + new Pagination("MessageListData", "page[cursor]", "page[size]"), + false); + + /** + * Get message details + * + * GET /messages/{messageId} (getMessage) + */ + public static final Operation GET_MESSAGE = new Operation<>( + "GET /messages/{messageId}", + "getMessage", + "GET", + "/messages/{messageId}", + AuthSurface.TEAM, + List.of("team"), + List.of("messageId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Get message events + * + * GET /messages/{messageId}/events (listMessageEvents) + */ + public static final Operation> LIST_MESSAGE_EVENTS = new Operation<>( + "GET /messages/{messageId}/events", + "listMessageEvents", + "GET", + "/messages/{messageId}/events", + AuthSurface.TEAM, + List.of("team"), + List.of("messageId"), + "ListMessageEventsQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + new Pagination("MessageEventData", "page[cursor]", "page[size]"), + false); + + /** + * Get message HTML content + * + * GET /messages/{messageId}/html (getMessageHtml) + */ + public static final Operation GET_MESSAGE_HTML = new Operation<>( + "GET /messages/{messageId}/html", + "getMessageHtml", + "GET", + "/messages/{messageId}/html", + AuthSurface.TEAM, + List.of("team"), + List.of("messageId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "text/html; charset=UTF-8", + ResponseKind.TEXT, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Get message source + * + * GET /messages/{messageId}/source (getMessageSource) + */ + public static final Operation GET_MESSAGE_SOURCE = new Operation<>( + "GET /messages/{messageId}/source", + "getMessageSource", + "GET", + "/messages/{messageId}/source", + AuthSurface.TEAM, + List.of("team"), + List.of("messageId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "message/rfc822", + ResponseKind.TEXT, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ErrorMessage", "ApiError"), 404, List.of("ErrorMessage", "ApiError"), 410, List.of("ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Get message plain text content + * + * GET /messages/{messageId}/text (getMessageText) + */ + public static final Operation GET_MESSAGE_TEXT = new Operation<>( + "GET /messages/{messageId}/text", + "getMessageText", + "GET", + "/messages/{messageId}/text", + AuthSurface.TEAM, + List.of("team"), + List.of("messageId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "text/plain; charset=UTF-8", + ResponseKind.TEXT, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Ping the API + * + * GET /ping (ping) + */ + public static final Operation PING = new Operation<>( + "GET /ping", + "ping", + "GET", + "/ping", + AuthSurface.EITHER, + List.of("sending", "team"), + List.of(), + null, + List.of(), + null, + null, + false, + List.of(200), + "text/html; charset=UTF-8", + ResponseKind.TEXT, + new TypeReference() {}, + errors(401, List.of("ApiError", "ErrorMessage"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * List all projects for the team + * + * GET /projects (listProjects) + */ + public static final Operation> LIST_PROJECTS = new Operation<>( + "GET /projects", + "listProjects", + "GET", + "/projects", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "ListProjectsQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + new Pagination("ProjectListData", "page[cursor]", "page[size]"), + false); + + /** + * Get project details + * + * GET /projects/{projectId} (getProject) + */ + public static final Operation GET_PROJECT = new Operation<>( + "GET /projects/{projectId}", + "getProject", + "GET", + "/projects/{projectId}", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + "GetProjectQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Get report forwarding settings + * + * GET /projects/{projectId}/report-forwarding (getReportForwarding) + */ + public static final Operation GET_REPORT_FORWARDING = new Operation<>( + "GET /projects/{projectId}/report-forwarding", + "getReportForwarding", + "GET", + "/projects/{projectId}/report-forwarding", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * List routes for a project + * + * GET /projects/{projectId}/routes (listRoutes) + */ + public static final Operation> LIST_ROUTES = new Operation<>( + "GET /projects/{projectId}/routes", + "listRoutes", + "GET", + "/projects/{projectId}/routes", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + "ListRoutesQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + new Pagination("RouteListData", "page[cursor]", "page[size]"), + false); + + /** + * Get route details + * + * GET /routes/{routeId} (getRoute) + */ + public static final Operation GET_ROUTE = new Operation<>( + "GET /routes/{routeId}", + "getRoute", + "GET", + "/routes/{routeId}", + AuthSurface.TEAM, + List.of("team"), + List.of("routeId"), + "GetRouteQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Get message statistics + * + * GET /stats (getStats) + */ + public static final Operation GET_STATS = new Operation<>( + "GET /stats", + "getStats", + "GET", + "/stats", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "GetStatsQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * List all suppressions for the team + * + * GET /suppressions (listSuppressions) + */ + public static final Operation> LIST_SUPPRESSIONS = new Operation<>( + "GET /suppressions", + "listSuppressions", + "GET", + "/suppressions", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "ListSuppressionsQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage")), + new Pagination("SuppressedRecipientData", "page[cursor]", "page[size]"), + false); + + /** + * Get team details + * + * GET /team (getTeam) + */ + public static final Operation GET_TEAM = new Operation<>( + "GET /team", + "getTeam", + "GET", + "/team", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "GetTeamQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Get team members + * + * GET /team/members (listTeamMembers) + */ + public static final Operation> LIST_TEAM_MEMBERS = new Operation<>( + "GET /team/members", + "listTeamMembers", + "GET", + "/team/members", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "ListTeamMembersQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 409, List.of("RbacConflictException"), 429, List.of("ErrorMessage")), + new Pagination("TeamMemberData", "page[cursor]", "page[size]"), + false); + + /** + * Get a team member + * + * GET /team/members/{userId} (getTeamMember) + */ + public static final Operation GET_TEAM_MEMBER = new Operation<>( + "GET /team/members/{userId}", + "getTeamMember", + "GET", + "/team/members/{userId}", + AuthSurface.TEAM, + List.of("team"), + List.of("userId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 409, List.of("RbacConflictException"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Get reusable team roles + * + * GET /team/roles (listTeamRoles) + */ + public static final Operation LIST_TEAM_ROLES = new Operation<>( + "GET /team/roles", + "listTeamRoles", + "GET", + "/team/roles", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Get team usage statistics + * + * GET /team/usage (getTeamUsage) + */ + public static final Operation GET_TEAM_USAGE = new Operation<>( + "GET /team/usage", + "getTeamUsage", + "GET", + "/team/usage", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * List all webhooks for the team + * + * GET /webhooks (listWebhooks) + */ + public static final Operation> LIST_WEBHOOKS = new Operation<>( + "GET /webhooks", + "listWebhooks", + "GET", + "/webhooks", + AuthSurface.TEAM, + List.of("team"), + List.of(), + "ListWebhooksQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + new Pagination("WebhookListData", "cursor", "page[size]"), + false); + + /** + * Get webhook details + * + * GET /webhooks/{webhookId} (getWebhook) + */ + public static final Operation GET_WEBHOOK = new Operation<>( + "GET /webhooks/{webhookId}", + "getWebhook", + "GET", + "/webhooks/{webhookId}", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Get webhook deliveries + * + * GET /webhooks/{webhookId}/deliveries (listWebhookDeliveries) + */ + public static final Operation> LIST_WEBHOOK_DELIVERIES = new Operation<>( + "GET /webhooks/{webhookId}/deliveries", + "listWebhookDeliveries", + "GET", + "/webhooks/{webhookId}/deliveries", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId"), + "ListWebhookDeliveriesQuery", + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage")), + new Pagination("WebhookDeliveryListData", "cursor", null), + false); + + /** + * Get a specific webhook delivery + * + * GET /webhooks/{webhookId}/deliveries/{deliveryId} (getWebhookDelivery) + */ + public static final Operation GET_WEBHOOK_DELIVERY = new Operation<>( + "GET /webhooks/{webhookId}/deliveries/{deliveryId}", + "getWebhookDelivery", + "GET", + "/webhooks/{webhookId}/deliveries/{deliveryId}", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId", "deliveryId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ApiError", "ErrorMessage"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Reschedule a message + * + * PATCH /messages/{messageId} (rescheduleMessage) + */ + public static final Operation RESCHEDULE_MESSAGE = new Operation<>( + "PATCH /messages/{messageId}", + "rescheduleMessage", + "PATCH", + "/messages/{messageId}", + AuthSurface.EITHER, + List.of("team"), + List.of("messageId"), + null, + List.of(), + "RescheduleMessageRequest", + "application/json", + true, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError", "ErrorMessage"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 409, List.of("ApiError", "ErrorMessage"), 422, List.of("ApiError", "ValidationError", "ErrorMessage")), + null, + false); + + /** + * Query email analytics + * + * POST /analytics (queryAnalytics) + */ + public static final Operation QUERY_ANALYTICS = new Operation<>( + "POST /analytics", + "queryAnalytics", + "POST", + "/analytics", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + "AnalyticsQuery", + "application/json", + true, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(400, List.of("ErrorMessage"), 401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 415, List.of("ErrorMessage"), 422, List.of("ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Create a new domain + * + * POST /domains (createDomain) + */ + public static final Operation CREATE_DOMAIN = new Operation<>( + "POST /domains", + "createDomain", + "POST", + "/domains", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + "StoreDomainData", + "application/json", + true, + List.of(201), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError"), 500, List.of("ApiError")), + null, + false); + + /** + * Verify all DNS records for a domain + * + * POST /domains/{domainId}/dns-records/verify (verifyDomainDnsRecords) + */ + public static final Operation VERIFY_DOMAIN_DNS_RECORDS = new Operation<>( + "POST /domains/{domainId}/dns-records/verify", + "verifyDomainDnsRecords", + "POST", + "/domains/{domainId}/dns-records/verify", + AuthSurface.TEAM, + List.of("team"), + List.of("domainId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("DnsVerificationFailureResponse"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Verify a specific DNS record + * + * POST /domains/{domainId}/dns-records/{recordId}/verify (verifyDomainDnsRecord) + */ + public static final Operation VERIFY_DOMAIN_DNS_RECORD = new Operation<>( + "POST /domains/{domainId}/dns-records/{recordId}/verify", + "verifyDomainDnsRecord", + "POST", + "/domains/{domainId}/dns-records/{recordId}/verify", + AuthSurface.TEAM, + List.of("team"), + List.of("domainId", "recordId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ApiError", "ErrorMessage"), 422, List.of("DnsRecordVerificationFailureResponse"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Cancel a scheduled message + * + * POST /messages/{messageId}/cancel (cancelScheduledMessage) + */ + public static final Operation CANCEL_SCHEDULED_MESSAGE = new Operation<>( + "POST /messages/{messageId}/cancel", + "cancelScheduledMessage", + "POST", + "/messages/{messageId}/cancel", + AuthSurface.EITHER, + List.of("team"), + List.of("messageId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 409, List.of("ApiError", "ErrorMessage"), 422, List.of("ErrorMessage")), + null, + false); + + /** + * Process one quarantined inbound message + * + * POST /messages/{messageId}/process (processInboundMessage) + */ + public static final Operation PROCESS_INBOUND_MESSAGE = new Operation<>( + "POST /messages/{messageId}/process", + "processInboundMessage", + "POST", + "/messages/{messageId}/process", + AuthSurface.TEAM, + List.of("team"), + List.of("messageId"), + null, + List.of("Idempotency-Key"), + null, + null, + false, + List.of(202), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 409, List.of("ProcessInboundMessageConflict", "ErrorMessage"), 422, List.of("ErrorMessage"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Create a new project + * + * POST /projects (createProject) + */ + public static final Operation CREATE_PROJECT = new Operation<>( + "POST /projects", + "createProject", + "POST", + "/projects", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + "StoreProjectData", + "application/json", + true, + List.of(201), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Resend report forwarding verification code + * + * POST /projects/{projectId}/report-forwarding/resend-code (resendReportForwardingCode) + */ + public static final Operation RESEND_REPORT_FORWARDING_CODE = new Operation<>( + "POST /projects/{projectId}/report-forwarding/resend-code", + "resendReportForwardingCode", + "POST", + "/projects/{projectId}/report-forwarding/resend-code", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Verify report forwarding destination + * + * POST /projects/{projectId}/report-forwarding/verify (verifyReportForwarding) + */ + public static final Operation VERIFY_REPORT_FORWARDING = new Operation<>( + "POST /projects/{projectId}/report-forwarding/verify", + "verifyReportForwarding", + "POST", + "/projects/{projectId}/report-forwarding/verify", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + "VerifyReportForwardingRequest", + "application/json", + true, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Rotate Project API token (legacy) + * + * POST /projects/{projectId}/rotate-token (rotateProjectToken) + * @deprecated Deprecated by the API. + */ + @Deprecated + public static final Operation ROTATE_PROJECT_TOKEN = new Operation<>( + "POST /projects/{projectId}/rotate-token", + "rotateProjectToken", + "POST", + "/projects/{projectId}/rotate-token", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage")), + null, + true); + + /** + * Create a new route + * + * POST /projects/{projectId}/routes (createRoute) + */ + public static final Operation CREATE_ROUTE = new Operation<>( + "POST /projects/{projectId}/routes", + "createRoute", + "POST", + "/projects/{projectId}/routes", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + "StoreRouteData", + "application/json", + true, + List.of(201), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("ApiError", "ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Verify inbound domain for a route + * + * POST /routes/{routeId}/verify-inbound-domain (verifyRouteInboundDomain) + */ + public static final Operation VERIFY_ROUTE_INBOUND_DOMAIN = new Operation<>( + "POST /routes/{routeId}/verify-inbound-domain", + "verifyRouteInboundDomain", + "POST", + "/routes/{routeId}/verify-inbound-domain", + AuthSurface.TEAM, + List.of("team"), + List.of("routeId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("InboundDomainVerificationResponse", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Send an email + * + * POST /send (sendMail) + */ + public static final Operation SEND_MAIL = new Operation<>( + "POST /send", + "sendMail", + "POST", + "/send", + AuthSurface.SENDING, + List.of("sending"), + List.of(), + null, + List.of("Idempotency-Key"), + "SendMailRequest", + "application/json", + true, + List.of(202), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 409, List.of("ErrorMessage"), 422, List.of("ErrorMessage", "ApiError", "ValidationError"), 429, List.of("ApiError"), 500, List.of("ApiError")), + null, + false); + + /** + * Send multiple emails in a batch + * + * POST /send/batch (sendBatchMail) + */ + public static final Operation> SEND_BATCH_MAIL = new Operation<>( + "POST /send/batch", + "sendBatchMail", + "POST", + "/send/batch", + AuthSurface.SENDING, + List.of("sending"), + List.of(), + null, + List.of("Idempotency-Key"), + "List", + "application/json", + true, + List.of(202), + "application/json", + ResponseKind.JSON, + new TypeReference>() {}, + errors(401, List.of("ErrorMessage"), 403, List.of("ApiError"), 409, List.of("ErrorMessage"), 422, List.of("ApiError", "ValidationError", "ErrorMessage"), 429, List.of("ApiError"), 500, List.of("ApiError")), + null, + false); + + /** + * Add email(s) to suppression list + * + * POST /suppressions (createSuppressions) + */ + public static final Operation CREATE_SUPPRESSIONS = new Operation<>( + "POST /suppressions", + "createSuppressions", + "POST", + "/suppressions", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + "StoreSuppressionData", + "application/json", + true, + List.of(201), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Create a new webhook + * + * POST /webhooks (createWebhook) + */ + public static final Operation CREATE_WEBHOOK = new Operation<>( + "POST /webhooks", + "createWebhook", + "POST", + "/webhooks", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + "StoreWebhookData", + "application/json", + true, + List.of(201), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Regenerate webhook secret + * + * POST /webhooks/{webhookId}/regenerate-secret (regenerateWebhookSecret) + */ + public static final Operation REGENERATE_WEBHOOK_SECRET = new Operation<>( + "POST /webhooks/{webhookId}/regenerate-secret", + "regenerateWebhookSecret", + "POST", + "/webhooks/{webhookId}/regenerate-secret", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Test a webhook by sending a sample payload + * + * POST /webhooks/{webhookId}/test (testWebhook) + */ + public static final Operation TEST_WEBHOOK = new Operation<>( + "POST /webhooks/{webhookId}/test", + "testWebhook", + "POST", + "/webhooks/{webhookId}/test", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId"), + null, + List.of(), + null, + null, + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Update projects associated with a domain + * + * PUT /domains/{domainId}/projects (updateDomainProjects) + */ + public static final Operation UPDATE_DOMAIN_PROJECTS = new Operation<>( + "PUT /domains/{domainId}/projects", + "updateDomainProjects", + "PUT", + "/domains/{domainId}/projects", + AuthSurface.TEAM, + List.of("team"), + List.of("domainId"), + null, + List.of(), + "UpdateDomainProjectsData", + "application/json", + true, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("ApiError", "ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Update project settings + * + * PUT /projects/{projectId} (updateProject) + */ + public static final Operation UPDATE_PROJECT = new Operation<>( + "PUT /projects/{projectId}", + "updateProject", + "PUT", + "/projects/{projectId}", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + "UpdateProjectData", + "application/json", + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Update report forwarding destination + * + * PUT /projects/{projectId}/report-forwarding (updateReportForwarding) + */ + public static final Operation UPDATE_REPORT_FORWARDING = new Operation<>( + "PUT /projects/{projectId}/report-forwarding", + "updateReportForwarding", + "PUT", + "/projects/{projectId}/report-forwarding", + AuthSurface.TEAM, + List.of("team"), + List.of("projectId"), + null, + List.of(), + "ReportForwardingRequest", + "application/json", + true, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Update route settings + * + * PUT /routes/{routeId} (updateRoute) + */ + public static final Operation UPDATE_ROUTE = new Operation<>( + "PUT /routes/{routeId}", + "updateRoute", + "PUT", + "/routes/{routeId}", + AuthSurface.TEAM, + List.of("team"), + List.of("routeId"), + null, + List.of(), + "UpdateRouteData", + "application/json", + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** + * Update team settings + * + * PUT /team (updateTeam) + */ + public static final Operation UPDATE_TEAM = new Operation<>( + "PUT /team", + "updateTeam", + "PUT", + "/team", + AuthSurface.TEAM, + List.of("team"), + List.of(), + null, + List.of(), + "UpdateTeamData", + "application/json", + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Replace a team member's assignment + * + * PUT /team/members/{userId}/assignment (updateTeamMemberAssignment) + */ + public static final Operation UPDATE_TEAM_MEMBER_ASSIGNMENT = new Operation<>( + "PUT /team/members/{userId}/assignment", + "updateTeamMemberAssignment", + "PUT", + "/team/members/{userId}/assignment", + AuthSurface.TEAM, + List.of("team"), + List.of("userId"), + null, + List.of(), + "UpdateTeamMemberAssignmentData", + "application/json", + true, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ApiError"), 403, List.of("ApiError"), 404, List.of("ErrorMessage", "ApiError"), 409, List.of("RbacConflictException"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage")), + null, + false); + + /** + * Update webhook settings + * + * PUT /webhooks/{webhookId} (updateWebhook) + */ + public static final Operation UPDATE_WEBHOOK = new Operation<>( + "PUT /webhooks/{webhookId}", + "updateWebhook", + "PUT", + "/webhooks/{webhookId}", + AuthSurface.TEAM, + List.of("team"), + List.of("webhookId"), + null, + List.of(), + "UpdateWebhookData", + "application/json", + false, + List.of(200), + "application/json", + ResponseKind.JSON, + new TypeReference() {}, + errors(401, List.of("ErrorMessage", "ApiError"), 403, List.of("ApiError", "ErrorMessage"), 404, List.of("ErrorMessage", "ApiError"), 422, List.of("ValidationError"), 429, List.of("ErrorMessage", "ApiError")), + null, + false); + + /** Every operation, keyed by {@code }, sorted by key. */ + public static final Map> ALL = all( + DELETE_DOMAIN, + DELETE_PROJECT, + DELETE_REPORT_FORWARDING, + DELETE_ROUTE, + DELETE_SUPPRESSION, + DELETE_WEBHOOK, + LIST_BLOCKED_FILE_TYPES, + LIST_DOMAINS, + GET_DOMAIN, + LIST_MESSAGES, + GET_MESSAGE, + LIST_MESSAGE_EVENTS, + GET_MESSAGE_HTML, + GET_MESSAGE_SOURCE, + GET_MESSAGE_TEXT, + PING, + LIST_PROJECTS, + GET_PROJECT, + GET_REPORT_FORWARDING, + LIST_ROUTES, + GET_ROUTE, + GET_STATS, + LIST_SUPPRESSIONS, + GET_TEAM, + LIST_TEAM_MEMBERS, + GET_TEAM_MEMBER, + LIST_TEAM_ROLES, + GET_TEAM_USAGE, + LIST_WEBHOOKS, + GET_WEBHOOK, + LIST_WEBHOOK_DELIVERIES, + GET_WEBHOOK_DELIVERY, + RESCHEDULE_MESSAGE, + QUERY_ANALYTICS, + CREATE_DOMAIN, + VERIFY_DOMAIN_DNS_RECORDS, + VERIFY_DOMAIN_DNS_RECORD, + CANCEL_SCHEDULED_MESSAGE, + PROCESS_INBOUND_MESSAGE, + CREATE_PROJECT, + RESEND_REPORT_FORWARDING_CODE, + VERIFY_REPORT_FORWARDING, + ROTATE_PROJECT_TOKEN, + CREATE_ROUTE, + VERIFY_ROUTE_INBOUND_DOMAIN, + SEND_MAIL, + SEND_BATCH_MAIL, + CREATE_SUPPRESSIONS, + CREATE_WEBHOOK, + REGENERATE_WEBHOOK_SECRET, + TEST_WEBHOOK, + UPDATE_DOMAIN_PROJECTS, + UPDATE_PROJECT, + UPDATE_REPORT_FORWARDING, + UPDATE_ROUTE, + UPDATE_TEAM, + UPDATE_TEAM_MEMBER_ASSIGNMENT, + UPDATE_WEBHOOK); + + private static Map> all(Operation... operations) { + Map> all = new LinkedHashMap<>(); + for (Operation operation : operations) { + all.put(operation.key(), operation); + } + return Collections.unmodifiableMap(all); + } + + @SuppressWarnings("unchecked") + private static Map> errors(Object... statusAndNames) { + Map> errors = new LinkedHashMap<>(); + for (int i = 0; i < statusAndNames.length; i += 2) { + errors.put((Integer) statusAndNames[i], (List) statusAndNames[i + 1]); + } + return Collections.unmodifiableMap(errors); + } +} diff --git a/src/main/java/co/lettermint/types/OptionalNullable.java b/src/main/java/co/lettermint/types/OptionalNullable.java new file mode 100644 index 0000000..4244fb9 --- /dev/null +++ b/src/main/java/co/lettermint/types/OptionalNullable.java @@ -0,0 +1,122 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; + +import java.io.IOException; +import java.util.Objects; + +/** + * A field that is optional and nullable in a request: a null reference omits the field, OptionalNullable.ofNull() sends JSON null, and OptionalNullable.of(value) sends the value. + * + * @param the value type + */ +@JsonSerialize(using = OptionalNullable.Serializer.class) +@JsonDeserialize(using = OptionalNullable.Deserializer.class) +public final class OptionalNullable { + private static final OptionalNullable NULL = new OptionalNullable<>(null); + + private final T value; + + private OptionalNullable(T value) { + this.value = value; + } + + /** A present value; {@code null} gives {@link #ofNull()}. */ + public static OptionalNullable of(T value) { + return value == null ? ofNull() : new OptionalNullable<>(value); + } + + /** An explicit JSON {@code null}. */ + @SuppressWarnings("unchecked") + public static OptionalNullable ofNull() { + return (OptionalNullable) NULL; + } + + /** The value, or {@code null} for an explicit JSON null. */ + public T value() { + return value; + } + + /** Whether this is an explicit JSON null. */ + public boolean isNull() { + return value == null; + } + + @Override + public boolean equals(Object other) { + return other instanceof OptionalNullable that && Objects.equals(value, that.value); + } + + @Override + public int hashCode() { + return Objects.hashCode(value); + } + + @Override + public String toString() { + return String.valueOf(value); + } + + /** Writes the value, or JSON {@code null}. */ + public static final class Serializer extends JsonSerializer> { + @Override + public void serialize(OptionalNullable value, JsonGenerator generator, SerializerProvider provider) throws IOException { + if (value.value == null) { + generator.writeNull(); + } else { + provider.defaultSerializeValue(value.value, generator); + } + } + } + + /** Reads a value or JSON {@code null}; an absent field stays a {@code null} reference. */ + public static final class Deserializer extends JsonDeserializer> implements ContextualDeserializer { + private final JavaType valueType; + + /** Used by Jackson. */ + public Deserializer() { + this(null); + } + + private Deserializer(JavaType valueType) { + this.valueType = valueType; + } + + @Override + public JsonDeserializer createContextual(DeserializationContext context, BeanProperty property) { + JavaType type = property != null ? property.getType() : context.getContextualType(); + return new Deserializer(type.containedTypeOrUnknown(0)); + } + + @Override + public OptionalNullable getNullValue(DeserializationContext context) { + return OptionalNullable.ofNull(); + } + + @Override + public Object getAbsentValue(DeserializationContext context) { + return null; + } + + @Override + public OptionalNullable deserialize(JsonParser parser, DeserializationContext context) throws IOException { + return OptionalNullable.of(context.readValue(parser, valueType)); + } + } +} diff --git a/src/main/java/co/lettermint/types/PendingSendMailResponse.java b/src/main/java/co/lettermint/types/PendingSendMailResponse.java new file mode 100644 index 0000000..5a48653 --- /dev/null +++ b/src/main/java/co/lettermint/types/PendingSendMailResponse.java @@ -0,0 +1,84 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An accepted message that is queued for delivery. + * + * @param messageId Always present. + * @param status Always present. + * @param sandbox Present when the project uses Sandbox delivery. Optional: null when absent. + * @param sandboxResult The simulated delivery result. Present when the project uses Sandbox delivery. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record PendingSendMailResponse( + @JsonProperty("message_id") String messageId, + @JsonProperty("status") String status, + @JsonProperty("sandbox") Boolean sandbox, + @JsonProperty("sandbox_result") SandboxResult sandboxResult +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this PendingSendMailResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messageId = messageId; + builder.status = status; + builder.sandbox = sandbox; + builder.sandboxResult = sandboxResult; + return builder; + } + + /** Builds a {@link PendingSendMailResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String messageId; + private String status; + private Boolean sandbox; + private SandboxResult sandboxResult; + + private Builder() { + } + + /** Sets {@code message_id}. */ + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(String status) { + this.status = status; + return this; + } + + /** Sets {@code sandbox}. */ + public Builder sandbox(Boolean sandbox) { + this.sandbox = sandbox; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Returns the {@link PendingSendMailResponse}. */ + public PendingSendMailResponse build() { + return new PendingSendMailResponse(messageId, status, sandbox, sandboxResult); + } + } +} diff --git a/src/main/java/co/lettermint/types/Plan.java b/src/main/java/co/lettermint/types/Plan.java new file mode 100644 index 0000000..943a0a9 --- /dev/null +++ b/src/main/java/co/lettermint/types/Plan.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class Plan { + /** {@code "free"} */ + public static final Plan FREE = new Plan("free"); + + /** {@code "starter"} */ + public static final Plan STARTER = new Plan("starter"); + + /** {@code "growth"} */ + public static final Plan GROWTH = new Plan("growth"); + + /** {@code "pro"} */ + public static final Plan PRO = new Plan("pro"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(FREE.value, FREE); + known.put(STARTER.value, STARTER); + known.put(GROWTH.value, GROWTH); + known.put(PRO.value, PRO); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private Plan(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static Plan of(String value) { + Objects.requireNonNull(value, "value"); + Plan known = KNOWN.get(value); + return known != null ? known : new Plan(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof Plan that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java b/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java new file mode 100644 index 0000000..efcb02d --- /dev/null +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param error Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProcessInboundMessageConflict( + @JsonProperty("error") ProcessInboundMessageConflictError error +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProcessInboundMessageConflict. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.error = error; + return builder; + } + + /** Builds a {@link ProcessInboundMessageConflict}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProcessInboundMessageConflictError error; + + private Builder() { + } + + /** Sets {@code error}. */ + public Builder error(ProcessInboundMessageConflictError error) { + this.error = error; + return this; + } + + /** Returns the {@link ProcessInboundMessageConflict}. */ + public ProcessInboundMessageConflict build() { + return new ProcessInboundMessageConflict(error); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java new file mode 100644 index 0000000..fa0ca7e --- /dev/null +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param code Always present. + * @param message Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProcessInboundMessageConflictError( + @JsonProperty("code") ProcessInboundMessageConflictErrorCode code, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProcessInboundMessageConflictError. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.code = code; + builder.message = message; + return builder; + } + + /** Builds a {@link ProcessInboundMessageConflictError}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProcessInboundMessageConflictErrorCode code; + private String message; + + private Builder() { + } + + /** Sets {@code code}. */ + public Builder code(ProcessInboundMessageConflictErrorCode code) { + this.code = code; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link ProcessInboundMessageConflictError}. */ + public ProcessInboundMessageConflictError build() { + return new ProcessInboundMessageConflictError(code, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java new file mode 100644 index 0000000..c5d47e8 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ProcessInboundMessageConflictErrorCode { + /** {@code "INBOUND_MESSAGE_NOT_QUARANTINED"} */ + public static final ProcessInboundMessageConflictErrorCode INBOUND_MESSAGE_NOT_QUARANTINED = new ProcessInboundMessageConflictErrorCode("INBOUND_MESSAGE_NOT_QUARANTINED"); + + /** {@code "INBOUND_WEBHOOK_NOT_CONFIGURED"} */ + public static final ProcessInboundMessageConflictErrorCode INBOUND_WEBHOOK_NOT_CONFIGURED = new ProcessInboundMessageConflictErrorCode("INBOUND_WEBHOOK_NOT_CONFIGURED"); + + /** {@code "MESSAGE_SOURCE_UNAVAILABLE"} */ + public static final ProcessInboundMessageConflictErrorCode MESSAGE_SOURCE_UNAVAILABLE = new ProcessInboundMessageConflictErrorCode("MESSAGE_SOURCE_UNAVAILABLE"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(INBOUND_MESSAGE_NOT_QUARANTINED.value, INBOUND_MESSAGE_NOT_QUARANTINED); + known.put(INBOUND_WEBHOOK_NOT_CONFIGURED.value, INBOUND_WEBHOOK_NOT_CONFIGURED); + known.put(MESSAGE_SOURCE_UNAVAILABLE.value, MESSAGE_SOURCE_UNAVAILABLE); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ProcessInboundMessageConflictErrorCode(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ProcessInboundMessageConflictErrorCode of(String value) { + Objects.requireNonNull(value, "value"); + ProcessInboundMessageConflictErrorCode known = KNOWN.get(value); + return known != null ? known : new ProcessInboundMessageConflictErrorCode(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ProcessInboundMessageConflictErrorCode that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java b/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java new file mode 100644 index 0000000..144ca14 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java @@ -0,0 +1,54 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The queued release of a quarantined inbound message. + * + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProcessInboundMessageResponse( + @JsonProperty("data") ProcessInboundMessageResult data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProcessInboundMessageResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link ProcessInboundMessageResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProcessInboundMessageResult data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ProcessInboundMessageResult data) { + this.data = data; + return this; + } + + /** Returns the {@link ProcessInboundMessageResponse}. */ + public ProcessInboundMessageResponse build() { + return new ProcessInboundMessageResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java b/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java new file mode 100644 index 0000000..cc26ee7 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java @@ -0,0 +1,80 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A quarantined inbound message that was queued for webhook delivery. + * + * @param messageId Always present. + * @param status Always present. + * @param webhookTargetCount The number of webhooks the message is delivered to. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProcessInboundMessageResult( + @JsonProperty("message_id") String messageId, + @JsonProperty("status") String status, + @JsonProperty("webhook_target_count") Long webhookTargetCount +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProcessInboundMessageResult. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messageId = messageId; + builder.status = status; + builder.webhookTargetCount = webhookTargetCount; + return builder; + } + + /** Builds a {@link ProcessInboundMessageResult}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String messageId; + private String status; + private Long webhookTargetCount; + + private Builder() { + } + + /** Sets {@code message_id}. */ + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(String status) { + this.status = status; + return this; + } + + /** Sets {@code webhook_target_count}. */ + public Builder webhookTargetCount(Long webhookTargetCount) { + this.webhookTargetCount = webhookTargetCount; + return this; + } + + /** Sets {@code webhook_target_count}. */ + public Builder webhookTargetCount(long webhookTargetCount) { + this.webhookTargetCount = webhookTargetCount; + return this; + } + + /** Returns the {@link ProcessInboundMessageResult}. */ + public ProcessInboundMessageResult build() { + return new ProcessInboundMessageResult(messageId, status, webhookTargetCount); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProjectAccessScope.java b/src/main/java/co/lettermint/types/ProjectAccessScope.java new file mode 100644 index 0000000..439ed7e --- /dev/null +++ b/src/main/java/co/lettermint/types/ProjectAccessScope.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class ProjectAccessScope { + /** {@code "all"} */ + public static final ProjectAccessScope ALL = new ProjectAccessScope("all"); + + /** {@code "selected"} */ + public static final ProjectAccessScope SELECTED = new ProjectAccessScope("selected"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(ALL.value, ALL); + known.put(SELECTED.value, SELECTED); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private ProjectAccessScope(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static ProjectAccessScope of(String value) { + Objects.requireNonNull(value, "value"); + ProjectAccessScope known = KNOWN.get(value); + return known != null ? known : new ProjectAccessScope(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof ProjectAccessScope that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ProjectCreatedData.java b/src/main/java/co/lettermint/types/ProjectCreatedData.java new file mode 100644 index 0000000..04af7c0 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProjectCreatedData.java @@ -0,0 +1,80 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param data Always present. + * @param message Always present. + * @param apiToken Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProjectCreatedData( + @JsonProperty("data") ProjectData data, + @JsonProperty("message") String message, + @JsonProperty("api_token") String apiToken +) { + + /** Credentials (api_token) are shown as {@code [redacted]}. */ + @Override + public String toString() { + return "ProjectCreatedData[data=" + data + + ", message=" + message + + ", apiToken=" + (apiToken == null ? "null" : "[redacted]") + "]"; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProjectCreatedData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + builder.apiToken = apiToken; + return builder; + } + + /** Builds a {@link ProjectCreatedData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProjectData data; + private String message; + private String apiToken; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ProjectData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code api_token}. */ + public Builder apiToken(String apiToken) { + this.apiToken = apiToken; + return this; + } + + /** Returns the {@link ProjectCreatedData}. */ + public ProjectCreatedData build() { + return new ProjectCreatedData(data, message, apiToken); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProjectData.java b/src/main/java/co/lettermint/types/ProjectData.java new file mode 100644 index 0000000..ec93402 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProjectData.java @@ -0,0 +1,221 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param name Always present. + * @param deliveryMode Always present. + * @param smtpEnabled Always present. + * @param redactEmailContent Always present. + * @param defaultRouteId Always present; may be null. + * @param tokenGeneratedAt Always present; may be null. + * @param tokenLastUsedAt Always present; may be null. + * @param tokenLastUsedIp Always present; may be null. + * @param routes Optional: null when absent. + * @param routesCount Optional: null when absent. + * @param domains Optional: null when absent. + * @param domainsCount Optional: null when absent. + * @param last28Days Optional and nullable: null when absent or null. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProjectData( + @JsonProperty("id") String id, + @JsonProperty("name") String name, + @JsonProperty("delivery_mode") DeliveryMode deliveryMode, + @JsonProperty("smtp_enabled") Boolean smtpEnabled, + @JsonProperty("redact_email_content") Boolean redactEmailContent, + @JsonProperty("default_route_id") String defaultRouteId, + @JsonProperty("token_generated_at") String tokenGeneratedAt, + @JsonProperty("token_last_used_at") String tokenLastUsedAt, + @JsonProperty("token_last_used_ip") String tokenLastUsedIp, + @JsonProperty("routes") List routes, + @JsonProperty("routes_count") Long routesCount, + @JsonProperty("domains") List domains, + @JsonProperty("domains_count") Long domainsCount, + @JsonProperty("last_28_days") MessageStatsData last28Days, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public ProjectData { + routes = Copies.list(routes); + domains = Copies.list(domains); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProjectData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + builder.deliveryMode = deliveryMode; + builder.smtpEnabled = smtpEnabled; + builder.redactEmailContent = redactEmailContent; + builder.defaultRouteId = defaultRouteId; + builder.tokenGeneratedAt = tokenGeneratedAt; + builder.tokenLastUsedAt = tokenLastUsedAt; + builder.tokenLastUsedIp = tokenLastUsedIp; + builder.routes = routes; + builder.routesCount = routesCount; + builder.domains = domains; + builder.domainsCount = domainsCount; + builder.last28Days = last28Days; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link ProjectData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + private DeliveryMode deliveryMode; + private Boolean smtpEnabled; + private Boolean redactEmailContent; + private String defaultRouteId; + private String tokenGeneratedAt; + private String tokenLastUsedAt; + private String tokenLastUsedIp; + private List routes; + private Long routesCount; + private List domains; + private Long domainsCount; + private MessageStatsData last28Days; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code delivery_mode}. */ + public Builder deliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = deliveryMode; + return this; + } + + /** Sets {@code smtp_enabled}. */ + public Builder smtpEnabled(Boolean smtpEnabled) { + this.smtpEnabled = smtpEnabled; + return this; + } + + /** Sets {@code redact_email_content}. */ + public Builder redactEmailContent(Boolean redactEmailContent) { + this.redactEmailContent = redactEmailContent; + return this; + } + + /** Sets {@code default_route_id}. */ + public Builder defaultRouteId(String defaultRouteId) { + this.defaultRouteId = defaultRouteId; + return this; + } + + /** Sets {@code token_generated_at}. */ + public Builder tokenGeneratedAt(String tokenGeneratedAt) { + this.tokenGeneratedAt = tokenGeneratedAt; + return this; + } + + /** Sets {@code token_last_used_at}. */ + public Builder tokenLastUsedAt(String tokenLastUsedAt) { + this.tokenLastUsedAt = tokenLastUsedAt; + return this; + } + + /** Sets {@code token_last_used_ip}. */ + public Builder tokenLastUsedIp(String tokenLastUsedIp) { + this.tokenLastUsedIp = tokenLastUsedIp; + return this; + } + + /** Sets {@code routes}. */ + public Builder routes(List routes) { + this.routes = routes; + return this; + } + + /** Sets {@code routes_count}. */ + public Builder routesCount(Long routesCount) { + this.routesCount = routesCount; + return this; + } + + /** Sets {@code routes_count}. */ + public Builder routesCount(long routesCount) { + this.routesCount = routesCount; + return this; + } + + /** Sets {@code domains}. */ + public Builder domains(List domains) { + this.domains = domains; + return this; + } + + /** Sets {@code domains_count}. */ + public Builder domainsCount(Long domainsCount) { + this.domainsCount = domainsCount; + return this; + } + + /** Sets {@code domains_count}. */ + public Builder domainsCount(long domainsCount) { + this.domainsCount = domainsCount; + return this; + } + + /** Sets {@code last_28_days}. */ + public Builder last28Days(MessageStatsData last28Days) { + this.last28Days = last28Days; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link ProjectData}. */ + public ProjectData build() { + return new ProjectData(id, name, deliveryMode, smtpEnabled, redactEmailContent, defaultRouteId, tokenGeneratedAt, tokenLastUsedAt, tokenLastUsedIp, routes, routesCount, domains, domainsCount, last28Days, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProjectListData.java b/src/main/java/co/lettermint/types/ProjectListData.java new file mode 100644 index 0000000..0909c11 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProjectListData.java @@ -0,0 +1,144 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param name Always present. + * @param deliveryMode Always present. + * @param smtpEnabled Always present. + * @param routesCount Always present. + * @param domainsCount Always present. + * @param last28Days Always present. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProjectListData( + @JsonProperty("id") String id, + @JsonProperty("name") String name, + @JsonProperty("delivery_mode") DeliveryMode deliveryMode, + @JsonProperty("smtp_enabled") Boolean smtpEnabled, + @JsonProperty("routes_count") Long routesCount, + @JsonProperty("domains_count") Long domainsCount, + @JsonProperty("last_28_days") MessageStatsData last28Days, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProjectListData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + builder.deliveryMode = deliveryMode; + builder.smtpEnabled = smtpEnabled; + builder.routesCount = routesCount; + builder.domainsCount = domainsCount; + builder.last28Days = last28Days; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link ProjectListData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + private DeliveryMode deliveryMode; + private Boolean smtpEnabled; + private Long routesCount; + private Long domainsCount; + private MessageStatsData last28Days; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code delivery_mode}. */ + public Builder deliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = deliveryMode; + return this; + } + + /** Sets {@code smtp_enabled}. */ + public Builder smtpEnabled(Boolean smtpEnabled) { + this.smtpEnabled = smtpEnabled; + return this; + } + + /** Sets {@code routes_count}. */ + public Builder routesCount(Long routesCount) { + this.routesCount = routesCount; + return this; + } + + /** Sets {@code routes_count}. */ + public Builder routesCount(long routesCount) { + this.routesCount = routesCount; + return this; + } + + /** Sets {@code domains_count}. */ + public Builder domainsCount(Long domainsCount) { + this.domainsCount = domainsCount; + return this; + } + + /** Sets {@code domains_count}. */ + public Builder domainsCount(long domainsCount) { + this.domainsCount = domainsCount; + return this; + } + + /** Sets {@code last_28_days}. */ + public Builder last28Days(MessageStatsData last28Days) { + this.last28Days = last28Days; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link ProjectListData}. */ + public ProjectListData build() { + return new ProjectListData(id, name, deliveryMode, smtpEnabled, routesCount, domainsCount, last28Days, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/ProjectMutationResponse.java b/src/main/java/co/lettermint/types/ProjectMutationResponse.java new file mode 100644 index 0000000..621acc0 --- /dev/null +++ b/src/main/java/co/lettermint/types/ProjectMutationResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The project after a change, with a confirmation message. + * + * @param data Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ProjectMutationResponse( + @JsonProperty("data") ProjectData data, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ProjectMutationResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + return builder; + } + + /** Builds a {@link ProjectMutationResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProjectData data; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ProjectData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link ProjectMutationResponse}. */ + public ProjectMutationResponse build() { + return new ProjectMutationResponse(data, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/QueryParameters.java b/src/main/java/co/lettermint/types/QueryParameters.java new file mode 100644 index 0000000..adfb1b3 --- /dev/null +++ b/src/main/java/co/lettermint/types/QueryParameters.java @@ -0,0 +1,21 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import java.util.Map; + +/** Query parameters of an operation, implemented by every generated <Op>Query. */ +public interface QueryParameters { + /** + * The parameters by wire name ({@code page[size]}, {@code filter[status]}, {@code sort}) in the order of the + * specification. Values are strings, numbers, booleans, open enums, lists or generated records; the SDK + * serializes them with bracket syntax and leaves out {@code null}. + * + * @return a new, modifiable map + */ + Map toParameters(); +} diff --git a/src/main/java/co/lettermint/types/RbacConflictCode.java b/src/main/java/co/lettermint/types/RbacConflictCode.java new file mode 100644 index 0000000..a9cf987 --- /dev/null +++ b/src/main/java/co/lettermint/types/RbacConflictCode.java @@ -0,0 +1,94 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class RbacConflictCode { + /** {@code "stale_resource"} */ + public static final RbacConflictCode STALE_RESOURCE = new RbacConflictCode("stale_resource"); + + /** {@code "owner_protected"} */ + public static final RbacConflictCode OWNER_PROTECTED = new RbacConflictCode("owner_protected"); + + /** {@code "last_owner"} */ + public static final RbacConflictCode LAST_OWNER = new RbacConflictCode("last_owner"); + + /** {@code "built_in_role_immutable"} */ + public static final RbacConflictCode BUILT_IN_ROLE_IMMUTABLE = new RbacConflictCode("built_in_role_immutable"); + + /** {@code "custom_role_requires_pro"} */ + public static final RbacConflictCode CUSTOM_ROLE_REQUIRES_PRO = new RbacConflictCode("custom_role_requires_pro"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(STALE_RESOURCE.value, STALE_RESOURCE); + known.put(OWNER_PROTECTED.value, OWNER_PROTECTED); + known.put(LAST_OWNER.value, LAST_OWNER); + known.put(BUILT_IN_ROLE_IMMUTABLE.value, BUILT_IN_ROLE_IMMUTABLE); + known.put(CUSTOM_ROLE_REQUIRES_PRO.value, CUSTOM_ROLE_REQUIRES_PRO); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private RbacConflictCode(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static RbacConflictCode of(String value) { + Objects.requireNonNull(value, "value"); + RbacConflictCode known = KNOWN.get(value); + return known != null ? known : new RbacConflictCode(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof RbacConflictCode that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/RbacConflictException.java b/src/main/java/co/lettermint/types/RbacConflictException.java new file mode 100644 index 0000000..d63d060 --- /dev/null +++ b/src/main/java/co/lettermint/types/RbacConflictException.java @@ -0,0 +1,54 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Role or project-access state conflict + * + * @param error Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RbacConflictException( + @JsonProperty("error") RbacConflictExceptionError error +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RbacConflictException. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.error = error; + return builder; + } + + /** Builds a {@link RbacConflictException}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private RbacConflictExceptionError error; + + private Builder() { + } + + /** Sets {@code error}. */ + public Builder error(RbacConflictExceptionError error) { + this.error = error; + return this; + } + + /** Returns the {@link RbacConflictException}. */ + public RbacConflictException build() { + return new RbacConflictException(error); + } + } +} diff --git a/src/main/java/co/lettermint/types/RbacConflictExceptionError.java b/src/main/java/co/lettermint/types/RbacConflictExceptionError.java new file mode 100644 index 0000000..d6ae5d9 --- /dev/null +++ b/src/main/java/co/lettermint/types/RbacConflictExceptionError.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param code Always present. + * @param message Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RbacConflictExceptionError( + @JsonProperty("code") RbacConflictCode code, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RbacConflictExceptionError. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.code = code; + builder.message = message; + return builder; + } + + /** Builds a {@link RbacConflictExceptionError}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private RbacConflictCode code; + private String message; + + private Builder() { + } + + /** Sets {@code code}. */ + public Builder code(RbacConflictCode code) { + this.code = code; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link RbacConflictExceptionError}. */ + public RbacConflictExceptionError build() { + return new RbacConflictExceptionError(code, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/RbacPermission.java b/src/main/java/co/lettermint/types/RbacPermission.java new file mode 100644 index 0000000..b956a78 --- /dev/null +++ b/src/main/java/co/lettermint/types/RbacPermission.java @@ -0,0 +1,238 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class RbacPermission { + /** {@code "team:manage"} */ + public static final RbacPermission TEAM_MANAGE = new RbacPermission("team:manage"); + + /** {@code "billing:manage"} */ + public static final RbacPermission BILLING_MANAGE = new RbacPermission("billing:manage"); + + /** {@code "security:manage"} */ + public static final RbacPermission SECURITY_MANAGE = new RbacPermission("security:manage"); + + /** {@code "audit:read"} */ + public static final RbacPermission AUDIT_READ = new RbacPermission("audit:read"); + + /** {@code "support:manage"} */ + public static final RbacPermission SUPPORT_MANAGE = new RbacPermission("support:manage"); + + /** {@code "members:read"} */ + public static final RbacPermission MEMBERS_READ = new RbacPermission("members:read"); + + /** {@code "members:manage"} */ + public static final RbacPermission MEMBERS_MANAGE = new RbacPermission("members:manage"); + + /** {@code "roles:manage"} */ + public static final RbacPermission ROLES_MANAGE = new RbacPermission("roles:manage"); + + /** {@code "team_tokens:read"} */ + public static final RbacPermission TEAM_TOKENS_READ = new RbacPermission("team_tokens:read"); + + /** {@code "team_tokens:manage"} */ + public static final RbacPermission TEAM_TOKENS_MANAGE = new RbacPermission("team_tokens:manage"); + + /** {@code "team_tokens:rotate"} */ + public static final RbacPermission TEAM_TOKENS_ROTATE = new RbacPermission("team_tokens:rotate"); + + /** {@code "team_tokens:revoke"} */ + public static final RbacPermission TEAM_TOKENS_REVOKE = new RbacPermission("team_tokens:revoke"); + + /** {@code "projects:create"} */ + public static final RbacPermission PROJECTS_CREATE = new RbacPermission("projects:create"); + + /** {@code "team_suppressions:read"} */ + public static final RbacPermission TEAM_SUPPRESSIONS_READ = new RbacPermission("team_suppressions:read"); + + /** {@code "team_suppressions:add"} */ + public static final RbacPermission TEAM_SUPPRESSIONS_ADD = new RbacPermission("team_suppressions:add"); + + /** {@code "team_suppressions:remove"} */ + public static final RbacPermission TEAM_SUPPRESSIONS_REMOVE = new RbacPermission("team_suppressions:remove"); + + /** {@code "projects:read"} */ + public static final RbacPermission PROJECTS_READ = new RbacPermission("projects:read"); + + /** {@code "projects:manage"} */ + public static final RbacPermission PROJECTS_MANAGE = new RbacPermission("projects:manage"); + + /** {@code "projects:delete"} */ + public static final RbacPermission PROJECTS_DELETE = new RbacPermission("projects:delete"); + + /** {@code "routes:read"} */ + public static final RbacPermission ROUTES_READ = new RbacPermission("routes:read"); + + /** {@code "routes:manage"} */ + public static final RbacPermission ROUTES_MANAGE = new RbacPermission("routes:manage"); + + /** {@code "routes:delete"} */ + public static final RbacPermission ROUTES_DELETE = new RbacPermission("routes:delete"); + + /** {@code "domains:read"} */ + public static final RbacPermission DOMAINS_READ = new RbacPermission("domains:read"); + + /** {@code "domains:manage"} */ + public static final RbacPermission DOMAINS_MANAGE = new RbacPermission("domains:manage"); + + /** {@code "domains:delete"} */ + public static final RbacPermission DOMAINS_DELETE = new RbacPermission("domains:delete"); + + /** {@code "project_tokens:read"} */ + public static final RbacPermission PROJECT_TOKENS_READ = new RbacPermission("project_tokens:read"); + + /** {@code "project_tokens:manage"} */ + public static final RbacPermission PROJECT_TOKENS_MANAGE = new RbacPermission("project_tokens:manage"); + + /** {@code "project_tokens:rotate"} */ + public static final RbacPermission PROJECT_TOKENS_ROTATE = new RbacPermission("project_tokens:rotate"); + + /** {@code "project_tokens:revoke"} */ + public static final RbacPermission PROJECT_TOKENS_REVOKE = new RbacPermission("project_tokens:revoke"); + + /** {@code "webhooks:read"} */ + public static final RbacPermission WEBHOOKS_READ = new RbacPermission("webhooks:read"); + + /** {@code "webhooks:manage"} */ + public static final RbacPermission WEBHOOKS_MANAGE = new RbacPermission("webhooks:manage"); + + /** {@code "webhooks:delete"} */ + public static final RbacPermission WEBHOOKS_DELETE = new RbacPermission("webhooks:delete"); + + /** {@code "webhooks:rotate_secret"} */ + public static final RbacPermission WEBHOOKS_ROTATE_SECRET = new RbacPermission("webhooks:rotate_secret"); + + /** {@code "stats:read"} */ + public static final RbacPermission STATS_READ = new RbacPermission("stats:read"); + + /** {@code "analytics:read"} */ + public static final RbacPermission ANALYTICS_READ = new RbacPermission("analytics:read"); + + /** {@code "messages:read"} */ + public static final RbacPermission MESSAGES_READ = new RbacPermission("messages:read"); + + /** {@code "messages:read_content"} */ + public static final RbacPermission MESSAGES_READ_CONTENT = new RbacPermission("messages:read_content"); + + /** {@code "messages:send"} */ + public static final RbacPermission MESSAGES_SEND = new RbacPermission("messages:send"); + + /** {@code "suppressions:read"} */ + public static final RbacPermission SUPPRESSIONS_READ = new RbacPermission("suppressions:read"); + + /** {@code "suppressions:add"} */ + public static final RbacPermission SUPPRESSIONS_ADD = new RbacPermission("suppressions:add"); + + /** {@code "suppressions:remove"} */ + public static final RbacPermission SUPPRESSIONS_REMOVE = new RbacPermission("suppressions:remove"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TEAM_MANAGE.value, TEAM_MANAGE); + known.put(BILLING_MANAGE.value, BILLING_MANAGE); + known.put(SECURITY_MANAGE.value, SECURITY_MANAGE); + known.put(AUDIT_READ.value, AUDIT_READ); + known.put(SUPPORT_MANAGE.value, SUPPORT_MANAGE); + known.put(MEMBERS_READ.value, MEMBERS_READ); + known.put(MEMBERS_MANAGE.value, MEMBERS_MANAGE); + known.put(ROLES_MANAGE.value, ROLES_MANAGE); + known.put(TEAM_TOKENS_READ.value, TEAM_TOKENS_READ); + known.put(TEAM_TOKENS_MANAGE.value, TEAM_TOKENS_MANAGE); + known.put(TEAM_TOKENS_ROTATE.value, TEAM_TOKENS_ROTATE); + known.put(TEAM_TOKENS_REVOKE.value, TEAM_TOKENS_REVOKE); + known.put(PROJECTS_CREATE.value, PROJECTS_CREATE); + known.put(TEAM_SUPPRESSIONS_READ.value, TEAM_SUPPRESSIONS_READ); + known.put(TEAM_SUPPRESSIONS_ADD.value, TEAM_SUPPRESSIONS_ADD); + known.put(TEAM_SUPPRESSIONS_REMOVE.value, TEAM_SUPPRESSIONS_REMOVE); + known.put(PROJECTS_READ.value, PROJECTS_READ); + known.put(PROJECTS_MANAGE.value, PROJECTS_MANAGE); + known.put(PROJECTS_DELETE.value, PROJECTS_DELETE); + known.put(ROUTES_READ.value, ROUTES_READ); + known.put(ROUTES_MANAGE.value, ROUTES_MANAGE); + known.put(ROUTES_DELETE.value, ROUTES_DELETE); + known.put(DOMAINS_READ.value, DOMAINS_READ); + known.put(DOMAINS_MANAGE.value, DOMAINS_MANAGE); + known.put(DOMAINS_DELETE.value, DOMAINS_DELETE); + known.put(PROJECT_TOKENS_READ.value, PROJECT_TOKENS_READ); + known.put(PROJECT_TOKENS_MANAGE.value, PROJECT_TOKENS_MANAGE); + known.put(PROJECT_TOKENS_ROTATE.value, PROJECT_TOKENS_ROTATE); + known.put(PROJECT_TOKENS_REVOKE.value, PROJECT_TOKENS_REVOKE); + known.put(WEBHOOKS_READ.value, WEBHOOKS_READ); + known.put(WEBHOOKS_MANAGE.value, WEBHOOKS_MANAGE); + known.put(WEBHOOKS_DELETE.value, WEBHOOKS_DELETE); + known.put(WEBHOOKS_ROTATE_SECRET.value, WEBHOOKS_ROTATE_SECRET); + known.put(STATS_READ.value, STATS_READ); + known.put(ANALYTICS_READ.value, ANALYTICS_READ); + known.put(MESSAGES_READ.value, MESSAGES_READ); + known.put(MESSAGES_READ_CONTENT.value, MESSAGES_READ_CONTENT); + known.put(MESSAGES_SEND.value, MESSAGES_SEND); + known.put(SUPPRESSIONS_READ.value, SUPPRESSIONS_READ); + known.put(SUPPRESSIONS_ADD.value, SUPPRESSIONS_ADD); + known.put(SUPPRESSIONS_REMOVE.value, SUPPRESSIONS_REMOVE); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private RbacPermission(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static RbacPermission of(String value) { + Objects.requireNonNull(value, "value"); + RbacPermission known = KNOWN.get(value); + return known != null ? known : new RbacPermission(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof RbacPermission that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/RecordType.java b/src/main/java/co/lettermint/types/RecordType.java new file mode 100644 index 0000000..cf6e3ab --- /dev/null +++ b/src/main/java/co/lettermint/types/RecordType.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class RecordType { + /** {@code "TXT"} */ + public static final RecordType TXT = new RecordType("TXT"); + + /** {@code "CNAME"} */ + public static final RecordType CNAME = new RecordType("CNAME"); + + /** {@code "MX"} */ + public static final RecordType MX = new RecordType("MX"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TXT.value, TXT); + known.put(CNAME.value, CNAME); + known.put(MX.value, MX); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private RecordType(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static RecordType of(String value) { + Objects.requireNonNull(value, "value"); + RecordType known = KNOWN.get(value); + return known != null ? known : new RecordType(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof RecordType that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ReportForwardingRequest.java b/src/main/java/co/lettermint/types/ReportForwardingRequest.java new file mode 100644 index 0000000..7d38d17 --- /dev/null +++ b/src/main/java/co/lettermint/types/ReportForwardingRequest.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param destination Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ReportForwardingRequest( + @JsonProperty("destination") String destination +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ReportForwardingRequest. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.destination = destination; + return builder; + } + + /** Builds a {@link ReportForwardingRequest}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String destination; + + private Builder() { + } + + /** Sets {@code destination}. */ + public Builder destination(String destination) { + this.destination = destination; + return this; + } + + /** Returns the {@link ReportForwardingRequest}. */ + public ReportForwardingRequest build() { + return new ReportForwardingRequest(destination); + } + } +} diff --git a/src/main/java/co/lettermint/types/ReportForwardingResource.java b/src/main/java/co/lettermint/types/ReportForwardingResource.java new file mode 100644 index 0000000..c2c8480 --- /dev/null +++ b/src/main/java/co/lettermint/types/ReportForwardingResource.java @@ -0,0 +1,72 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param destination Always present; may be null. + * @param verified Always present. + * @param verifiedAt Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ReportForwardingResource( + @JsonProperty("destination") String destination, + @JsonProperty("verified") Boolean verified, + @JsonProperty("verified_at") String verifiedAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ReportForwardingResource. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.destination = destination; + builder.verified = verified; + builder.verifiedAt = verifiedAt; + return builder; + } + + /** Builds a {@link ReportForwardingResource}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String destination; + private Boolean verified; + private String verifiedAt; + + private Builder() { + } + + /** Sets {@code destination}. */ + public Builder destination(String destination) { + this.destination = destination; + return this; + } + + /** Sets {@code verified}. */ + public Builder verified(Boolean verified) { + this.verified = verified; + return this; + } + + /** Sets {@code verified_at}. */ + public Builder verifiedAt(String verifiedAt) { + this.verifiedAt = verifiedAt; + return this; + } + + /** Returns the {@link ReportForwardingResource}. */ + public ReportForwardingResource build() { + return new ReportForwardingResource(destination, verified, verifiedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/RescheduleMessageRequest.java b/src/main/java/co/lettermint/types/RescheduleMessageRequest.java new file mode 100644 index 0000000..2e7ff92 --- /dev/null +++ b/src/main/java/co/lettermint/types/RescheduleMessageRequest.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param scheduledAt Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RescheduleMessageRequest( + @JsonProperty("scheduled_at") String scheduledAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RescheduleMessageRequest. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.scheduledAt = scheduledAt; + return builder; + } + + /** Builds a {@link RescheduleMessageRequest}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String scheduledAt; + + private Builder() { + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Returns the {@link RescheduleMessageRequest}. */ + public RescheduleMessageRequest build() { + return new RescheduleMessageRequest(scheduledAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java b/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java new file mode 100644 index 0000000..b6d7ee0 --- /dev/null +++ b/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ResendReportForwardingCodeResponse( + @JsonProperty("data") ReportForwardingResource data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ResendReportForwardingCodeResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link ResendReportForwardingCodeResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ReportForwardingResource data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ReportForwardingResource data) { + this.data = data; + return this; + } + + /** Returns the {@link ResendReportForwardingCodeResponse}. */ + public ResendReportForwardingCodeResponse build() { + return new ResendReportForwardingCodeResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java b/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java new file mode 100644 index 0000000..1bf6e8e --- /dev/null +++ b/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The project and its new legacy Project API token. + * + * @param data Always present. + * @param newToken The new Project API token. It is only returned once. Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RotateProjectTokenResponse( + @JsonProperty("data") ProjectData data, + @JsonProperty("new_token") String newToken, + @JsonProperty("message") String message +) { + + /** Credentials (new_token) are shown as {@code [redacted]}. */ + @Override + public String toString() { + return "RotateProjectTokenResponse[data=" + data + + ", newToken=" + (newToken == null ? "null" : "[redacted]") + + ", message=" + message + "]"; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RotateProjectTokenResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.newToken = newToken; + builder.message = message; + return builder; + } + + /** Builds a {@link RotateProjectTokenResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProjectData data; + private String newToken; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ProjectData data) { + this.data = data; + return this; + } + + /** Sets {@code new_token}. */ + public Builder newToken(String newToken) { + this.newToken = newToken; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link RotateProjectTokenResponse}. */ + public RotateProjectTokenResponse build() { + return new RotateProjectTokenResponse(data, newToken, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/RouteData.java b/src/main/java/co/lettermint/types/RouteData.java new file mode 100644 index 0000000..4ad4445 --- /dev/null +++ b/src/main/java/co/lettermint/types/RouteData.java @@ -0,0 +1,266 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param projectId Always present. + * @param slug Always present. + * @param name Always present. + * @param routeType Always present. + * @param isDefault Always present. + * @param inboundAddress Permanent compatibility address for this inbound route (<route-uuid-without-hyphens>@inbound.lettermint.co). It keeps working alongside the catch-all route domain. Optional and nullable: null when absent or null. + * @param inboundRouteDomain Catch-all receiving domain for this inbound route. Mail to any address at this domain reaches the route. Null for non-inbound routes. Optional and nullable: null when absent or null. + * @param inboundMxHostname Optional: null when absent. + * @param inboundDomain Optional and nullable: null when absent or null. + * @param inboundDomainVerifiedAt Optional and nullable: null when absent or null. + * @param inboundSpamThreshold Optional and nullable: null when absent or null. + * @param attachmentDelivery Optional: null when absent. + * @param settings Route settings available for this route type and team feature access. Optional and nullable: null when absent or null. + * @param project Optional: null when absent. + * @param webhooksCount Optional: null when absent. + * @param suppressedRecipientsCount Optional: null when absent. + * @param statistics Optional: null when absent. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RouteData( + @JsonProperty("id") String id, + @JsonProperty("project_id") String projectId, + @JsonProperty("slug") String slug, + @JsonProperty("name") String name, + @JsonProperty("route_type") RouteType routeType, + @JsonProperty("is_default") Boolean isDefault, + @JsonProperty("inbound_address") String inboundAddress, + @JsonProperty("inbound_route_domain") String inboundRouteDomain, + @JsonProperty("inbound_mx_hostname") String inboundMxHostname, + @JsonProperty("inbound_domain") String inboundDomain, + @JsonProperty("inbound_domain_verified_at") String inboundDomainVerifiedAt, + @JsonProperty("inbound_spam_threshold") Double inboundSpamThreshold, + @JsonProperty("attachment_delivery") AttachmentDelivery attachmentDelivery, + @JsonProperty("settings") RouteDataSettings settings, + @JsonProperty("project") ProjectData project, + @JsonProperty("webhooks_count") Long webhooksCount, + @JsonProperty("suppressed_recipients_count") Long suppressedRecipientsCount, + @JsonProperty("statistics") List statistics, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public RouteData { + statistics = Copies.list(statistics); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RouteData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.projectId = projectId; + builder.slug = slug; + builder.name = name; + builder.routeType = routeType; + builder.isDefault = isDefault; + builder.inboundAddress = inboundAddress; + builder.inboundRouteDomain = inboundRouteDomain; + builder.inboundMxHostname = inboundMxHostname; + builder.inboundDomain = inboundDomain; + builder.inboundDomainVerifiedAt = inboundDomainVerifiedAt; + builder.inboundSpamThreshold = inboundSpamThreshold; + builder.attachmentDelivery = attachmentDelivery; + builder.settings = settings; + builder.project = project; + builder.webhooksCount = webhooksCount; + builder.suppressedRecipientsCount = suppressedRecipientsCount; + builder.statistics = statistics; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link RouteData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String projectId; + private String slug; + private String name; + private RouteType routeType; + private Boolean isDefault; + private String inboundAddress; + private String inboundRouteDomain; + private String inboundMxHostname; + private String inboundDomain; + private String inboundDomainVerifiedAt; + private Double inboundSpamThreshold; + private AttachmentDelivery attachmentDelivery; + private RouteDataSettings settings; + private ProjectData project; + private Long webhooksCount; + private Long suppressedRecipientsCount; + private List statistics; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code project_id}. */ + public Builder projectId(String projectId) { + this.projectId = projectId; + return this; + } + + /** Sets {@code slug}. */ + public Builder slug(String slug) { + this.slug = slug; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code route_type}. */ + public Builder routeType(RouteType routeType) { + this.routeType = routeType; + return this; + } + + /** Sets {@code is_default}. */ + public Builder isDefault(Boolean isDefault) { + this.isDefault = isDefault; + return this; + } + + /** Sets {@code inbound_address}. */ + public Builder inboundAddress(String inboundAddress) { + this.inboundAddress = inboundAddress; + return this; + } + + /** Sets {@code inbound_route_domain}. */ + public Builder inboundRouteDomain(String inboundRouteDomain) { + this.inboundRouteDomain = inboundRouteDomain; + return this; + } + + /** Sets {@code inbound_mx_hostname}. */ + public Builder inboundMxHostname(String inboundMxHostname) { + this.inboundMxHostname = inboundMxHostname; + return this; + } + + /** Sets {@code inbound_domain}. */ + public Builder inboundDomain(String inboundDomain) { + this.inboundDomain = inboundDomain; + return this; + } + + /** Sets {@code inbound_domain_verified_at}. */ + public Builder inboundDomainVerifiedAt(String inboundDomainVerifiedAt) { + this.inboundDomainVerifiedAt = inboundDomainVerifiedAt; + return this; + } + + /** Sets {@code inbound_spam_threshold}. */ + public Builder inboundSpamThreshold(Double inboundSpamThreshold) { + this.inboundSpamThreshold = inboundSpamThreshold; + return this; + } + + /** Sets {@code inbound_spam_threshold}. */ + public Builder inboundSpamThreshold(double inboundSpamThreshold) { + this.inboundSpamThreshold = inboundSpamThreshold; + return this; + } + + /** Sets {@code attachment_delivery}. */ + public Builder attachmentDelivery(AttachmentDelivery attachmentDelivery) { + this.attachmentDelivery = attachmentDelivery; + return this; + } + + /** Sets {@code settings}. */ + public Builder settings(RouteDataSettings settings) { + this.settings = settings; + return this; + } + + /** Sets {@code project}. */ + public Builder project(ProjectData project) { + this.project = project; + return this; + } + + /** Sets {@code webhooks_count}. */ + public Builder webhooksCount(Long webhooksCount) { + this.webhooksCount = webhooksCount; + return this; + } + + /** Sets {@code webhooks_count}. */ + public Builder webhooksCount(long webhooksCount) { + this.webhooksCount = webhooksCount; + return this; + } + + /** Sets {@code suppressed_recipients_count}. */ + public Builder suppressedRecipientsCount(Long suppressedRecipientsCount) { + this.suppressedRecipientsCount = suppressedRecipientsCount; + return this; + } + + /** Sets {@code suppressed_recipients_count}. */ + public Builder suppressedRecipientsCount(long suppressedRecipientsCount) { + this.suppressedRecipientsCount = suppressedRecipientsCount; + return this; + } + + /** Sets {@code statistics}. */ + public Builder statistics(List statistics) { + this.statistics = statistics; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link RouteData}. */ + public RouteData build() { + return new RouteData(id, projectId, slug, name, routeType, isDefault, inboundAddress, inboundRouteDomain, inboundMxHostname, inboundDomain, inboundDomainVerifiedAt, inboundSpamThreshold, attachmentDelivery, settings, project, webhooksCount, suppressedRecipientsCount, statistics, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/RouteDataSettings.java b/src/main/java/co/lettermint/types/RouteDataSettings.java new file mode 100644 index 0000000..c96dc1e --- /dev/null +++ b/src/main/java/co/lettermint/types/RouteDataSettings.java @@ -0,0 +1,134 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Route settings available for this route type and team feature access + * + * @param disableHostedUnsubscribe Optional: null when absent. + * @param trackOpens Optional: null when absent. + * @param trackClicks Optional: null when absent. + * @param generatePlaintextFallback Optional: null when absent. + * @param suppressAutoResponders Optional: null when absent. + * @param suppressDisposableRecipients Optional: null when absent. + * @param tls Optional: null when absent. + * @param redactEmailContent Optional: null when absent. + * @param attachmentDelivery Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RouteDataSettings( + @JsonProperty("disable_hosted_unsubscribe") Boolean disableHostedUnsubscribe, + @JsonProperty("track_opens") Boolean trackOpens, + @JsonProperty("track_clicks") Boolean trackClicks, + @JsonProperty("generate_plaintext_fallback") Boolean generatePlaintextFallback, + @JsonProperty("suppress_auto_responders") Boolean suppressAutoResponders, + @JsonProperty("suppress_disposable_recipients") Boolean suppressDisposableRecipients, + @JsonProperty("tls") TlsPolicy tls, + @JsonProperty("redact_email_content") Boolean redactEmailContent, + @JsonProperty("attachment_delivery") AttachmentDelivery attachmentDelivery +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RouteDataSettings. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.disableHostedUnsubscribe = disableHostedUnsubscribe; + builder.trackOpens = trackOpens; + builder.trackClicks = trackClicks; + builder.generatePlaintextFallback = generatePlaintextFallback; + builder.suppressAutoResponders = suppressAutoResponders; + builder.suppressDisposableRecipients = suppressDisposableRecipients; + builder.tls = tls; + builder.redactEmailContent = redactEmailContent; + builder.attachmentDelivery = attachmentDelivery; + return builder; + } + + /** Builds a {@link RouteDataSettings}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean disableHostedUnsubscribe; + private Boolean trackOpens; + private Boolean trackClicks; + private Boolean generatePlaintextFallback; + private Boolean suppressAutoResponders; + private Boolean suppressDisposableRecipients; + private TlsPolicy tls; + private Boolean redactEmailContent; + private AttachmentDelivery attachmentDelivery; + + private Builder() { + } + + /** Sets {@code disable_hosted_unsubscribe}. */ + public Builder disableHostedUnsubscribe(Boolean disableHostedUnsubscribe) { + this.disableHostedUnsubscribe = disableHostedUnsubscribe; + return this; + } + + /** Sets {@code track_opens}. */ + public Builder trackOpens(Boolean trackOpens) { + this.trackOpens = trackOpens; + return this; + } + + /** Sets {@code track_clicks}. */ + public Builder trackClicks(Boolean trackClicks) { + this.trackClicks = trackClicks; + return this; + } + + /** Sets {@code generate_plaintext_fallback}. */ + public Builder generatePlaintextFallback(Boolean generatePlaintextFallback) { + this.generatePlaintextFallback = generatePlaintextFallback; + return this; + } + + /** Sets {@code suppress_auto_responders}. */ + public Builder suppressAutoResponders(Boolean suppressAutoResponders) { + this.suppressAutoResponders = suppressAutoResponders; + return this; + } + + /** Sets {@code suppress_disposable_recipients}. */ + public Builder suppressDisposableRecipients(Boolean suppressDisposableRecipients) { + this.suppressDisposableRecipients = suppressDisposableRecipients; + return this; + } + + /** Sets {@code tls}. */ + public Builder tls(TlsPolicy tls) { + this.tls = tls; + return this; + } + + /** Sets {@code redact_email_content}. */ + public Builder redactEmailContent(Boolean redactEmailContent) { + this.redactEmailContent = redactEmailContent; + return this; + } + + /** Sets {@code attachment_delivery}. */ + public Builder attachmentDelivery(AttachmentDelivery attachmentDelivery) { + this.attachmentDelivery = attachmentDelivery; + return this; + } + + /** Returns the {@link RouteDataSettings}. */ + public RouteDataSettings build() { + return new RouteDataSettings(disableHostedUnsubscribe, trackOpens, trackClicks, generatePlaintextFallback, suppressAutoResponders, suppressDisposableRecipients, tls, redactEmailContent, attachmentDelivery); + } + } +} diff --git a/src/main/java/co/lettermint/types/RouteListData.java b/src/main/java/co/lettermint/types/RouteListData.java new file mode 100644 index 0000000..e291f0d --- /dev/null +++ b/src/main/java/co/lettermint/types/RouteListData.java @@ -0,0 +1,144 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param slug Always present. + * @param name Always present. + * @param routeType Always present. + * @param isDefault Always present. + * @param webhooksCount Always present. + * @param suppressedRecipientsCount Always present. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RouteListData( + @JsonProperty("id") String id, + @JsonProperty("slug") String slug, + @JsonProperty("name") String name, + @JsonProperty("route_type") RouteType routeType, + @JsonProperty("is_default") Boolean isDefault, + @JsonProperty("webhooks_count") Long webhooksCount, + @JsonProperty("suppressed_recipients_count") Long suppressedRecipientsCount, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RouteListData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.slug = slug; + builder.name = name; + builder.routeType = routeType; + builder.isDefault = isDefault; + builder.webhooksCount = webhooksCount; + builder.suppressedRecipientsCount = suppressedRecipientsCount; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link RouteListData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String slug; + private String name; + private RouteType routeType; + private Boolean isDefault; + private Long webhooksCount; + private Long suppressedRecipientsCount; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code slug}. */ + public Builder slug(String slug) { + this.slug = slug; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code route_type}. */ + public Builder routeType(RouteType routeType) { + this.routeType = routeType; + return this; + } + + /** Sets {@code is_default}. */ + public Builder isDefault(Boolean isDefault) { + this.isDefault = isDefault; + return this; + } + + /** Sets {@code webhooks_count}. */ + public Builder webhooksCount(Long webhooksCount) { + this.webhooksCount = webhooksCount; + return this; + } + + /** Sets {@code webhooks_count}. */ + public Builder webhooksCount(long webhooksCount) { + this.webhooksCount = webhooksCount; + return this; + } + + /** Sets {@code suppressed_recipients_count}. */ + public Builder suppressedRecipientsCount(Long suppressedRecipientsCount) { + this.suppressedRecipientsCount = suppressedRecipientsCount; + return this; + } + + /** Sets {@code suppressed_recipients_count}. */ + public Builder suppressedRecipientsCount(long suppressedRecipientsCount) { + this.suppressedRecipientsCount = suppressedRecipientsCount; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link RouteListData}. */ + public RouteListData build() { + return new RouteListData(id, slug, name, routeType, isDefault, webhooksCount, suppressedRecipientsCount, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/RouteMutationResponse.java b/src/main/java/co/lettermint/types/RouteMutationResponse.java new file mode 100644 index 0000000..aa2a5ec --- /dev/null +++ b/src/main/java/co/lettermint/types/RouteMutationResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The route after it was created or changed, with a confirmation message. + * + * @param data Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RouteMutationResponse( + @JsonProperty("data") RouteData data, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RouteMutationResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + return builder; + } + + /** Builds a {@link RouteMutationResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private RouteData data; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(RouteData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link RouteMutationResponse}. */ + public RouteMutationResponse build() { + return new RouteMutationResponse(data, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/RouteStatisticData.java b/src/main/java/co/lettermint/types/RouteStatisticData.java new file mode 100644 index 0000000..050b976 --- /dev/null +++ b/src/main/java/co/lettermint/types/RouteStatisticData.java @@ -0,0 +1,260 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param date Always present. + * @param sentCount Always present. + * @param deliveredCount Always present. + * @param openedCount Always present. + * @param clickedCount Always present. + * @param hardBounceCount Always present. + * @param spamComplaintCount Always present. + * @param inboundReceivedCount Always present. + * @param observedOpenedCount Optional and nullable: null when absent or null. + * @param humanOpenedCount Optional and nullable: null when absent or null. + * @param privacyOpenedCount Optional and nullable: null when absent or null. + * @param effectiveOpenedCount Always present; may be null. + * @param machineOpenedCount Always present; may be null. + * @param machineClickedCount Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record RouteStatisticData( + @JsonProperty("date") String date, + @JsonProperty("sent_count") Long sentCount, + @JsonProperty("delivered_count") Long deliveredCount, + @JsonProperty("opened_count") Long openedCount, + @JsonProperty("clicked_count") Long clickedCount, + @JsonProperty("hard_bounce_count") Long hardBounceCount, + @JsonProperty("spam_complaint_count") Long spamComplaintCount, + @JsonProperty("inbound_received_count") Long inboundReceivedCount, + @JsonProperty("observed_opened_count") Long observedOpenedCount, + @JsonProperty("human_opened_count") Long humanOpenedCount, + @JsonProperty("privacy_opened_count") Long privacyOpenedCount, + @JsonProperty("effective_opened_count") Long effectiveOpenedCount, + @JsonProperty("machine_opened_count") Long machineOpenedCount, + @JsonProperty("machine_clicked_count") Long machineClickedCount +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this RouteStatisticData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.date = date; + builder.sentCount = sentCount; + builder.deliveredCount = deliveredCount; + builder.openedCount = openedCount; + builder.clickedCount = clickedCount; + builder.hardBounceCount = hardBounceCount; + builder.spamComplaintCount = spamComplaintCount; + builder.inboundReceivedCount = inboundReceivedCount; + builder.observedOpenedCount = observedOpenedCount; + builder.humanOpenedCount = humanOpenedCount; + builder.privacyOpenedCount = privacyOpenedCount; + builder.effectiveOpenedCount = effectiveOpenedCount; + builder.machineOpenedCount = machineOpenedCount; + builder.machineClickedCount = machineClickedCount; + return builder; + } + + /** Builds a {@link RouteStatisticData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String date; + private Long sentCount; + private Long deliveredCount; + private Long openedCount; + private Long clickedCount; + private Long hardBounceCount; + private Long spamComplaintCount; + private Long inboundReceivedCount; + private Long observedOpenedCount; + private Long humanOpenedCount; + private Long privacyOpenedCount; + private Long effectiveOpenedCount; + private Long machineOpenedCount; + private Long machineClickedCount; + + private Builder() { + } + + /** Sets {@code date}. */ + public Builder date(String date) { + this.date = date; + return this; + } + + /** Sets {@code sent_count}. */ + public Builder sentCount(Long sentCount) { + this.sentCount = sentCount; + return this; + } + + /** Sets {@code sent_count}. */ + public Builder sentCount(long sentCount) { + this.sentCount = sentCount; + return this; + } + + /** Sets {@code delivered_count}. */ + public Builder deliveredCount(Long deliveredCount) { + this.deliveredCount = deliveredCount; + return this; + } + + /** Sets {@code delivered_count}. */ + public Builder deliveredCount(long deliveredCount) { + this.deliveredCount = deliveredCount; + return this; + } + + /** Sets {@code opened_count}. */ + public Builder openedCount(Long openedCount) { + this.openedCount = openedCount; + return this; + } + + /** Sets {@code opened_count}. */ + public Builder openedCount(long openedCount) { + this.openedCount = openedCount; + return this; + } + + /** Sets {@code clicked_count}. */ + public Builder clickedCount(Long clickedCount) { + this.clickedCount = clickedCount; + return this; + } + + /** Sets {@code clicked_count}. */ + public Builder clickedCount(long clickedCount) { + this.clickedCount = clickedCount; + return this; + } + + /** Sets {@code hard_bounce_count}. */ + public Builder hardBounceCount(Long hardBounceCount) { + this.hardBounceCount = hardBounceCount; + return this; + } + + /** Sets {@code hard_bounce_count}. */ + public Builder hardBounceCount(long hardBounceCount) { + this.hardBounceCount = hardBounceCount; + return this; + } + + /** Sets {@code spam_complaint_count}. */ + public Builder spamComplaintCount(Long spamComplaintCount) { + this.spamComplaintCount = spamComplaintCount; + return this; + } + + /** Sets {@code spam_complaint_count}. */ + public Builder spamComplaintCount(long spamComplaintCount) { + this.spamComplaintCount = spamComplaintCount; + return this; + } + + /** Sets {@code inbound_received_count}. */ + public Builder inboundReceivedCount(Long inboundReceivedCount) { + this.inboundReceivedCount = inboundReceivedCount; + return this; + } + + /** Sets {@code inbound_received_count}. */ + public Builder inboundReceivedCount(long inboundReceivedCount) { + this.inboundReceivedCount = inboundReceivedCount; + return this; + } + + /** Sets {@code observed_opened_count}. */ + public Builder observedOpenedCount(Long observedOpenedCount) { + this.observedOpenedCount = observedOpenedCount; + return this; + } + + /** Sets {@code observed_opened_count}. */ + public Builder observedOpenedCount(long observedOpenedCount) { + this.observedOpenedCount = observedOpenedCount; + return this; + } + + /** Sets {@code human_opened_count}. */ + public Builder humanOpenedCount(Long humanOpenedCount) { + this.humanOpenedCount = humanOpenedCount; + return this; + } + + /** Sets {@code human_opened_count}. */ + public Builder humanOpenedCount(long humanOpenedCount) { + this.humanOpenedCount = humanOpenedCount; + return this; + } + + /** Sets {@code privacy_opened_count}. */ + public Builder privacyOpenedCount(Long privacyOpenedCount) { + this.privacyOpenedCount = privacyOpenedCount; + return this; + } + + /** Sets {@code privacy_opened_count}. */ + public Builder privacyOpenedCount(long privacyOpenedCount) { + this.privacyOpenedCount = privacyOpenedCount; + return this; + } + + /** Sets {@code effective_opened_count}. */ + public Builder effectiveOpenedCount(Long effectiveOpenedCount) { + this.effectiveOpenedCount = effectiveOpenedCount; + return this; + } + + /** Sets {@code effective_opened_count}. */ + public Builder effectiveOpenedCount(long effectiveOpenedCount) { + this.effectiveOpenedCount = effectiveOpenedCount; + return this; + } + + /** Sets {@code machine_opened_count}. */ + public Builder machineOpenedCount(Long machineOpenedCount) { + this.machineOpenedCount = machineOpenedCount; + return this; + } + + /** Sets {@code machine_opened_count}. */ + public Builder machineOpenedCount(long machineOpenedCount) { + this.machineOpenedCount = machineOpenedCount; + return this; + } + + /** Sets {@code machine_clicked_count}. */ + public Builder machineClickedCount(Long machineClickedCount) { + this.machineClickedCount = machineClickedCount; + return this; + } + + /** Sets {@code machine_clicked_count}. */ + public Builder machineClickedCount(long machineClickedCount) { + this.machineClickedCount = machineClickedCount; + return this; + } + + /** Returns the {@link RouteStatisticData}. */ + public RouteStatisticData build() { + return new RouteStatisticData(date, sentCount, deliveredCount, openedCount, clickedCount, hardBounceCount, spamComplaintCount, inboundReceivedCount, observedOpenedCount, humanOpenedCount, privacyOpenedCount, effectiveOpenedCount, machineOpenedCount, machineClickedCount); + } + } +} diff --git a/src/main/java/co/lettermint/types/RouteType.java b/src/main/java/co/lettermint/types/RouteType.java new file mode 100644 index 0000000..acc2c66 --- /dev/null +++ b/src/main/java/co/lettermint/types/RouteType.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class RouteType { + /** {@code "transactional"} */ + public static final RouteType TRANSACTIONAL = new RouteType("transactional"); + + /** {@code "broadcast"} */ + public static final RouteType BROADCAST = new RouteType("broadcast"); + + /** {@code "inbound"} */ + public static final RouteType INBOUND = new RouteType("inbound"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TRANSACTIONAL.value, TRANSACTIONAL); + known.put(BROADCAST.value, BROADCAST); + known.put(INBOUND.value, INBOUND); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private RouteType(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static RouteType of(String value) { + Objects.requireNonNull(value, "value"); + RouteType known = KNOWN.get(value); + return known != null ? known : new RouteType(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof RouteType that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SandboxResult.java b/src/main/java/co/lettermint/types/SandboxResult.java new file mode 100644 index 0000000..8ad9621 --- /dev/null +++ b/src/main/java/co/lettermint/types/SandboxResult.java @@ -0,0 +1,118 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class SandboxResult { + /** {@code "delivered"} */ + public static final SandboxResult DELIVERED = new SandboxResult("delivered"); + + /** {@code "hard_bounced"} */ + public static final SandboxResult HARD_BOUNCED = new SandboxResult("hard_bounced"); + + /** {@code "soft_bounced"} */ + public static final SandboxResult SOFT_BOUNCED = new SandboxResult("soft_bounced"); + + /** {@code "deferred"} */ + public static final SandboxResult DEFERRED = new SandboxResult("deferred"); + + /** {@code "failed"} */ + public static final SandboxResult FAILED = new SandboxResult("failed"); + + /** {@code "suppressed"} */ + public static final SandboxResult SUPPRESSED = new SandboxResult("suppressed"); + + /** {@code "spam_complaint"} */ + public static final SandboxResult SPAM_COMPLAINT = new SandboxResult("spam_complaint"); + + /** {@code "auto_replied"} */ + public static final SandboxResult AUTO_REPLIED = new SandboxResult("auto_replied"); + + /** {@code "opened"} */ + public static final SandboxResult OPENED = new SandboxResult("opened"); + + /** {@code "clicked"} */ + public static final SandboxResult CLICKED = new SandboxResult("clicked"); + + /** {@code "unsubscribed"} */ + public static final SandboxResult UNSUBSCRIBED = new SandboxResult("unsubscribed"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(DELIVERED.value, DELIVERED); + known.put(HARD_BOUNCED.value, HARD_BOUNCED); + known.put(SOFT_BOUNCED.value, SOFT_BOUNCED); + known.put(DEFERRED.value, DEFERRED); + known.put(FAILED.value, FAILED); + known.put(SUPPRESSED.value, SUPPRESSED); + known.put(SPAM_COMPLAINT.value, SPAM_COMPLAINT); + known.put(AUTO_REPLIED.value, AUTO_REPLIED); + known.put(OPENED.value, OPENED); + known.put(CLICKED.value, CLICKED); + known.put(UNSUBSCRIBED.value, UNSUBSCRIBED); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SandboxResult(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SandboxResult of(String value) { + Objects.requireNonNull(value, "value"); + SandboxResult known = KNOWN.get(value); + return known != null ? known : new SandboxResult(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SandboxResult that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/ScheduledMessage.java b/src/main/java/co/lettermint/types/ScheduledMessage.java new file mode 100644 index 0000000..3d5beb2 --- /dev/null +++ b/src/main/java/co/lettermint/types/ScheduledMessage.java @@ -0,0 +1,74 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The schedule state of a message after it was rescheduled or canceled. + * + * @param messageId Always present. + * @param status Always present; may be null. + * @param scheduledAt The scheduled delivery time in ISO 8601 format. Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ScheduledMessage( + @JsonProperty("message_id") String messageId, + @JsonProperty("status") MessageStatus status, + @JsonProperty("scheduled_at") String scheduledAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ScheduledMessage. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messageId = messageId; + builder.status = status; + builder.scheduledAt = scheduledAt; + return builder; + } + + /** Builds a {@link ScheduledMessage}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String messageId; + private MessageStatus status; + private String scheduledAt; + + private Builder() { + } + + /** Sets {@code message_id}. */ + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(MessageStatus status) { + this.status = status; + return this; + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Returns the {@link ScheduledMessage}. */ + public ScheduledMessage build() { + return new ScheduledMessage(messageId, status, scheduledAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java b/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java new file mode 100644 index 0000000..beb9c28 --- /dev/null +++ b/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java @@ -0,0 +1,94 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * An accepted message that is scheduled for later delivery. + * + * @param messageId Always present. + * @param status Always present. + * @param scheduledAt The scheduled delivery time in ISO 8601 format. Always present. + * @param sandbox Present when the project uses Sandbox delivery. Optional: null when absent. + * @param sandboxResult The simulated delivery result. Present when the project uses Sandbox delivery. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ScheduledSendMailResponse( + @JsonProperty("message_id") String messageId, + @JsonProperty("status") String status, + @JsonProperty("scheduled_at") String scheduledAt, + @JsonProperty("sandbox") Boolean sandbox, + @JsonProperty("sandbox_result") SandboxResult sandboxResult +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ScheduledSendMailResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messageId = messageId; + builder.status = status; + builder.scheduledAt = scheduledAt; + builder.sandbox = sandbox; + builder.sandboxResult = sandboxResult; + return builder; + } + + /** Builds a {@link ScheduledSendMailResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String messageId; + private String status; + private String scheduledAt; + private Boolean sandbox; + private SandboxResult sandboxResult; + + private Builder() { + } + + /** Sets {@code message_id}. */ + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(String status) { + this.status = status; + return this; + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Sets {@code sandbox}. */ + public Builder sandbox(Boolean sandbox) { + this.sandbox = sandbox; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Returns the {@link ScheduledSendMailResponse}. */ + public ScheduledSendMailResponse build() { + return new ScheduledSendMailResponse(messageId, status, scheduledAt, sandbox, sandboxResult); + } + } +} diff --git a/src/main/java/co/lettermint/types/SendMailRequest.java b/src/main/java/co/lettermint/types/SendMailRequest.java new file mode 100644 index 0000000..952bb97 --- /dev/null +++ b/src/main/java/co/lettermint/types/SendMailRequest.java @@ -0,0 +1,226 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +/** + * @param route Optional: null omits it. + * @param from Required. + * @param to Required. + * @param cc Optional: null omits it. + * @param bcc Optional: null omits it. + * @param replyTo Optional: null omits it. + * @param subject Required. + * @param scheduledAt ISO 8601 or English delivery time. A time without a timezone uses UTC. Optional: null omits it. + * @param sandboxResult The result that a Sandbox project simulates for every recipient. Optional: null omits it. + * @param headers Custom headers to include in the email. To preserve a submitted RFC Message-ID, include both Message-ID and X-LM-Preserve-Message-ID with a string value of true or 1. Header names and control values are case-insensitive; false or 0 retains replacement. Optional: null omits it. + * @param metadata Metadata to track with the email (not added as email headers). Optional: null omits it. + * @param tag Tag to categorize and filter emails (alphanumeric, underscores, hyphens, spaces allowed). Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param tags Reusable exact-match tags. Names must be unique and are case-sensitive. Optional: null omits it. + * @param settings Per-email settings that override the selected route settings for this email only. Optional: null omits it. + * @param html Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param text Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param attachments Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SendMailRequest( + @JsonProperty("route") String route, + @JsonProperty("from") String from, + @JsonProperty("to") List to, + @JsonProperty("cc") List cc, + @JsonProperty("bcc") List bcc, + @JsonProperty("reply_to") List replyTo, + @JsonProperty("subject") String subject, + @JsonProperty("scheduled_at") String scheduledAt, + @JsonProperty("sandbox_result") SandboxResult sandboxResult, + @JsonProperty("headers") Map headers, + @JsonProperty("metadata") Map metadata, + @JsonProperty("tag") OptionalNullable tag, + @JsonProperty("tags") List tags, + @JsonProperty("settings") SendMailRequestSettings settings, + @JsonProperty("html") OptionalNullable html, + @JsonProperty("text") OptionalNullable text, + @JsonProperty("attachments") List attachments +) { + /** Copies lists and maps into unmodifiable collections. */ + public SendMailRequest { + to = Copies.list(to); + cc = Copies.list(cc); + bcc = Copies.list(bcc); + replyTo = Copies.list(replyTo); + headers = Copies.map(headers); + metadata = Copies.map(metadata); + tags = Copies.list(tags); + attachments = Copies.list(attachments); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SendMailRequest. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.route = route; + builder.from = from; + builder.to = to; + builder.cc = cc; + builder.bcc = bcc; + builder.replyTo = replyTo; + builder.subject = subject; + builder.scheduledAt = scheduledAt; + builder.sandboxResult = sandboxResult; + builder.headers = headers; + builder.metadata = metadata; + builder.tag = tag; + builder.tags = tags; + builder.settings = settings; + builder.html = html; + builder.text = text; + builder.attachments = attachments; + return builder; + } + + /** Builds a {@link SendMailRequest}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String route; + private String from; + private List to; + private List cc; + private List bcc; + private List replyTo; + private String subject; + private String scheduledAt; + private SandboxResult sandboxResult; + private Map headers; + private Map metadata; + private OptionalNullable tag; + private List tags; + private SendMailRequestSettings settings; + private OptionalNullable html; + private OptionalNullable text; + private List attachments; + + private Builder() { + } + + /** Sets {@code route}. */ + public Builder route(String route) { + this.route = route; + return this; + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(List to) { + this.to = to; + return this; + } + + /** Sets {@code cc}. */ + public Builder cc(List cc) { + this.cc = cc; + return this; + } + + /** Sets {@code bcc}. */ + public Builder bcc(List bcc) { + this.bcc = bcc; + return this; + } + + /** Sets {@code reply_to}. */ + public Builder replyTo(List replyTo) { + this.replyTo = replyTo; + return this; + } + + /** Sets {@code subject}. */ + public Builder subject(String subject) { + this.subject = subject; + return this; + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Sets {@code headers}. */ + public Builder headers(Map headers) { + this.headers = headers; + return this; + } + + /** Sets {@code metadata}. */ + public Builder metadata(Map metadata) { + this.metadata = metadata; + return this; + } + + /** Sets {@code tag}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder tag(String tag) { + this.tag = OptionalNullable.of(tag); + return this; + } + + /** Sets {@code tags}. */ + public Builder tags(List tags) { + this.tags = tags; + return this; + } + + /** Sets {@code settings}. */ + public Builder settings(SendMailRequestSettings settings) { + this.settings = settings; + return this; + } + + /** Sets {@code html}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder html(String html) { + this.html = OptionalNullable.of(html); + return this; + } + + /** Sets {@code text}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder text(String text) { + this.text = OptionalNullable.of(text); + return this; + } + + /** Sets {@code attachments}. */ + public Builder attachments(List attachments) { + this.attachments = attachments; + return this; + } + + /** Returns the {@link SendMailRequest}. */ + public SendMailRequest build() { + return new SendMailRequest(route, from, to, cc, bcc, replyTo, subject, scheduledAt, sandboxResult, headers, metadata, tag, tags, settings, html, text, attachments); + } + } +} diff --git a/src/main/java/co/lettermint/types/SendMailRequestSettings.java b/src/main/java/co/lettermint/types/SendMailRequestSettings.java new file mode 100644 index 0000000..1750216 --- /dev/null +++ b/src/main/java/co/lettermint/types/SendMailRequestSettings.java @@ -0,0 +1,74 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Per-email settings that override the selected route settings for this email only. + * + * @param trackOpens Optional: null omits it. + * @param trackClicks Optional: null omits it. + * @param tls Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SendMailRequestSettings( + @JsonProperty("track_opens") Boolean trackOpens, + @JsonProperty("track_clicks") Boolean trackClicks, + @JsonProperty("tls") TlsPolicy tls +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SendMailRequestSettings. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.trackOpens = trackOpens; + builder.trackClicks = trackClicks; + builder.tls = tls; + return builder; + } + + /** Builds a {@link SendMailRequestSettings}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean trackOpens; + private Boolean trackClicks; + private TlsPolicy tls; + + private Builder() { + } + + /** Sets {@code track_opens}. */ + public Builder trackOpens(Boolean trackOpens) { + this.trackOpens = trackOpens; + return this; + } + + /** Sets {@code track_clicks}. */ + public Builder trackClicks(Boolean trackClicks) { + this.trackClicks = trackClicks; + return this; + } + + /** Sets {@code tls}. */ + public Builder tls(TlsPolicy tls) { + this.tls = tls; + return this; + } + + /** Returns the {@link SendMailRequestSettings}. */ + public SendMailRequestSettings build() { + return new SendMailRequestSettings(trackOpens, trackClicks, tls); + } + } +} diff --git a/src/main/java/co/lettermint/types/SendMailResponse.java b/src/main/java/co/lettermint/types/SendMailResponse.java new file mode 100644 index 0000000..3b2c0fd --- /dev/null +++ b/src/main/java/co/lettermint/types/SendMailResponse.java @@ -0,0 +1,92 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param messageId Always present. + * @param status Always present. + * @param sandbox Present when the project uses Sandbox delivery. Optional: null when absent. + * @param sandboxResult The simulated delivery result. Present when the project uses Sandbox delivery. Optional: null when absent. + * @param scheduledAt The scheduled delivery time in ISO 8601 format. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SendMailResponse( + @JsonProperty("message_id") String messageId, + @JsonProperty("status") MessageStatus status, + @JsonProperty("sandbox") Boolean sandbox, + @JsonProperty("sandbox_result") SandboxResult sandboxResult, + @JsonProperty("scheduled_at") String scheduledAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SendMailResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.messageId = messageId; + builder.status = status; + builder.sandbox = sandbox; + builder.sandboxResult = sandboxResult; + builder.scheduledAt = scheduledAt; + return builder; + } + + /** Builds a {@link SendMailResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String messageId; + private MessageStatus status; + private Boolean sandbox; + private SandboxResult sandboxResult; + private String scheduledAt; + + private Builder() { + } + + /** Sets {@code message_id}. */ + public Builder messageId(String messageId) { + this.messageId = messageId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(MessageStatus status) { + this.status = status; + return this; + } + + /** Sets {@code sandbox}. */ + public Builder sandbox(Boolean sandbox) { + this.sandbox = sandbox; + return this; + } + + /** Sets {@code sandbox_result}. */ + public Builder sandboxResult(SandboxResult sandboxResult) { + this.sandboxResult = sandboxResult; + return this; + } + + /** Sets {@code scheduled_at}. */ + public Builder scheduledAt(String scheduledAt) { + this.scheduledAt = scheduledAt; + return this; + } + + /** Returns the {@link SendMailResponse}. */ + public SendMailResponse build() { + return new SendMailResponse(messageId, status, sandbox, sandboxResult, scheduledAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/SpamSymbol.java b/src/main/java/co/lettermint/types/SpamSymbol.java new file mode 100644 index 0000000..9dc73b9 --- /dev/null +++ b/src/main/java/co/lettermint/types/SpamSymbol.java @@ -0,0 +1,94 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param name Always present. + * @param score Always present. + * @param options Always present. + * @param description Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SpamSymbol( + @JsonProperty("name") String name, + @JsonProperty("score") Double score, + @JsonProperty("options") List options, + @JsonProperty("description") String description +) { + /** Copies lists and maps into unmodifiable collections. */ + public SpamSymbol { + options = Copies.list(options); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SpamSymbol. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.score = score; + builder.options = options; + builder.description = description; + return builder; + } + + /** Builds a {@link SpamSymbol}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private Double score; + private List options; + private String description; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code score}. */ + public Builder score(Double score) { + this.score = score; + return this; + } + + /** Sets {@code score}. */ + public Builder score(double score) { + this.score = score; + return this; + } + + /** Sets {@code options}. */ + public Builder options(List options) { + this.options = options; + return this; + } + + /** Sets {@code description}. */ + public Builder description(String description) { + this.description = description; + return this; + } + + /** Returns the {@link SpamSymbol}. */ + public SpamSymbol build() { + return new SpamSymbol(name, score, options, description); + } + } +} diff --git a/src/main/java/co/lettermint/types/StatsDailyData.java b/src/main/java/co/lettermint/types/StatsDailyData.java new file mode 100644 index 0000000..fcebf6c --- /dev/null +++ b/src/main/java/co/lettermint/types/StatsDailyData.java @@ -0,0 +1,274 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param date Always present. + * @param sent Always present. + * @param delivered Always present. + * @param hardBounced Always present. + * @param spamComplaints Always present. + * @param opened Null when tracking is not enabled for this context. Always present; may be null. + * @param clicked Null when tracking is not enabled for this context. Always present; may be null. + * @param inbound Always present. + * @param transactional Null for team-scoped stats (only available when project_id is specified). Always present; may be null. + * @param broadcast Null for team-scoped stats (only available when project_id is specified). Always present; may be null. + * @param observedOpened Human opens plus unresolved privacy-proxy opens. Optional and nullable: null when absent or null. + * @param humanOpened Optional and nullable: null when absent or null. + * @param privacyOpened Optional and nullable: null when absent or null. + * @param effectiveOpened Always present; may be null. + * @param machineOpened Always present; may be null. + * @param machineClicked Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StatsDailyData( + @JsonProperty("date") String date, + @JsonProperty("sent") Long sent, + @JsonProperty("delivered") Long delivered, + @JsonProperty("hard_bounced") Long hardBounced, + @JsonProperty("spam_complaints") Long spamComplaints, + @JsonProperty("opened") Long opened, + @JsonProperty("clicked") Long clicked, + @JsonProperty("inbound") StatsInboundData inbound, + @JsonProperty("transactional") StatsTypeData transactional, + @JsonProperty("broadcast") StatsTypeData broadcast, + @JsonProperty("observed_opened") Long observedOpened, + @JsonProperty("human_opened") Long humanOpened, + @JsonProperty("privacy_opened") Long privacyOpened, + @JsonProperty("effective_opened") Long effectiveOpened, + @JsonProperty("machine_opened") Long machineOpened, + @JsonProperty("machine_clicked") Long machineClicked +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StatsDailyData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.date = date; + builder.sent = sent; + builder.delivered = delivered; + builder.hardBounced = hardBounced; + builder.spamComplaints = spamComplaints; + builder.opened = opened; + builder.clicked = clicked; + builder.inbound = inbound; + builder.transactional = transactional; + builder.broadcast = broadcast; + builder.observedOpened = observedOpened; + builder.humanOpened = humanOpened; + builder.privacyOpened = privacyOpened; + builder.effectiveOpened = effectiveOpened; + builder.machineOpened = machineOpened; + builder.machineClicked = machineClicked; + return builder; + } + + /** Builds a {@link StatsDailyData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String date; + private Long sent; + private Long delivered; + private Long hardBounced; + private Long spamComplaints; + private Long opened; + private Long clicked; + private StatsInboundData inbound; + private StatsTypeData transactional; + private StatsTypeData broadcast; + private Long observedOpened; + private Long humanOpened; + private Long privacyOpened; + private Long effectiveOpened; + private Long machineOpened; + private Long machineClicked; + + private Builder() { + } + + /** Sets {@code date}. */ + public Builder date(String date) { + this.date = date; + return this; + } + + /** Sets {@code sent}. */ + public Builder sent(Long sent) { + this.sent = sent; + return this; + } + + /** Sets {@code sent}. */ + public Builder sent(long sent) { + this.sent = sent; + return this; + } + + /** Sets {@code delivered}. */ + public Builder delivered(Long delivered) { + this.delivered = delivered; + return this; + } + + /** Sets {@code delivered}. */ + public Builder delivered(long delivered) { + this.delivered = delivered; + return this; + } + + /** Sets {@code hard_bounced}. */ + public Builder hardBounced(Long hardBounced) { + this.hardBounced = hardBounced; + return this; + } + + /** Sets {@code hard_bounced}. */ + public Builder hardBounced(long hardBounced) { + this.hardBounced = hardBounced; + return this; + } + + /** Sets {@code spam_complaints}. */ + public Builder spamComplaints(Long spamComplaints) { + this.spamComplaints = spamComplaints; + return this; + } + + /** Sets {@code spam_complaints}. */ + public Builder spamComplaints(long spamComplaints) { + this.spamComplaints = spamComplaints; + return this; + } + + /** Sets {@code opened}. */ + public Builder opened(Long opened) { + this.opened = opened; + return this; + } + + /** Sets {@code opened}. */ + public Builder opened(long opened) { + this.opened = opened; + return this; + } + + /** Sets {@code clicked}. */ + public Builder clicked(Long clicked) { + this.clicked = clicked; + return this; + } + + /** Sets {@code clicked}. */ + public Builder clicked(long clicked) { + this.clicked = clicked; + return this; + } + + /** Sets {@code inbound}. */ + public Builder inbound(StatsInboundData inbound) { + this.inbound = inbound; + return this; + } + + /** Sets {@code transactional}. */ + public Builder transactional(StatsTypeData transactional) { + this.transactional = transactional; + return this; + } + + /** Sets {@code broadcast}. */ + public Builder broadcast(StatsTypeData broadcast) { + this.broadcast = broadcast; + return this; + } + + /** Sets {@code observed_opened}. */ + public Builder observedOpened(Long observedOpened) { + this.observedOpened = observedOpened; + return this; + } + + /** Sets {@code observed_opened}. */ + public Builder observedOpened(long observedOpened) { + this.observedOpened = observedOpened; + return this; + } + + /** Sets {@code human_opened}. */ + public Builder humanOpened(Long humanOpened) { + this.humanOpened = humanOpened; + return this; + } + + /** Sets {@code human_opened}. */ + public Builder humanOpened(long humanOpened) { + this.humanOpened = humanOpened; + return this; + } + + /** Sets {@code privacy_opened}. */ + public Builder privacyOpened(Long privacyOpened) { + this.privacyOpened = privacyOpened; + return this; + } + + /** Sets {@code privacy_opened}. */ + public Builder privacyOpened(long privacyOpened) { + this.privacyOpened = privacyOpened; + return this; + } + + /** Sets {@code effective_opened}. */ + public Builder effectiveOpened(Long effectiveOpened) { + this.effectiveOpened = effectiveOpened; + return this; + } + + /** Sets {@code effective_opened}. */ + public Builder effectiveOpened(long effectiveOpened) { + this.effectiveOpened = effectiveOpened; + return this; + } + + /** Sets {@code machine_opened}. */ + public Builder machineOpened(Long machineOpened) { + this.machineOpened = machineOpened; + return this; + } + + /** Sets {@code machine_opened}. */ + public Builder machineOpened(long machineOpened) { + this.machineOpened = machineOpened; + return this; + } + + /** Sets {@code machine_clicked}. */ + public Builder machineClicked(Long machineClicked) { + this.machineClicked = machineClicked; + return this; + } + + /** Sets {@code machine_clicked}. */ + public Builder machineClicked(long machineClicked) { + this.machineClicked = machineClicked; + return this; + } + + /** Returns the {@link StatsDailyData}. */ + public StatsDailyData build() { + return new StatsDailyData(date, sent, delivered, hardBounced, spamComplaints, opened, clicked, inbound, transactional, broadcast, observedOpened, humanOpened, privacyOpened, effectiveOpened, machineOpened, machineClicked); + } + } +} diff --git a/src/main/java/co/lettermint/types/StatsData.java b/src/main/java/co/lettermint/types/StatsData.java new file mode 100644 index 0000000..63d0a2b --- /dev/null +++ b/src/main/java/co/lettermint/types/StatsData.java @@ -0,0 +1,88 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param from Always present. + * @param to Always present. + * @param totals Always present. + * @param daily Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StatsData( + @JsonProperty("from") String from, + @JsonProperty("to") String to, + @JsonProperty("totals") StatsTotalsData totals, + @JsonProperty("daily") List daily +) { + /** Copies lists and maps into unmodifiable collections. */ + public StatsData { + daily = Copies.list(daily); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StatsData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.from = from; + builder.to = to; + builder.totals = totals; + builder.daily = daily; + return builder; + } + + /** Builds a {@link StatsData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String from; + private String to; + private StatsTotalsData totals; + private List daily; + + private Builder() { + } + + /** Sets {@code from}. */ + public Builder from(String from) { + this.from = from; + return this; + } + + /** Sets {@code to}. */ + public Builder to(String to) { + this.to = to; + return this; + } + + /** Sets {@code totals}. */ + public Builder totals(StatsTotalsData totals) { + this.totals = totals; + return this; + } + + /** Sets {@code daily}. */ + public Builder daily(List daily) { + this.daily = daily; + return this; + } + + /** Returns the {@link StatsData}. */ + public StatsData build() { + return new StatsData(from, to, totals, daily); + } + } +} diff --git a/src/main/java/co/lettermint/types/StatsInboundData.java b/src/main/java/co/lettermint/types/StatsInboundData.java new file mode 100644 index 0000000..6d701b1 --- /dev/null +++ b/src/main/java/co/lettermint/types/StatsInboundData.java @@ -0,0 +1,58 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param received Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StatsInboundData( + @JsonProperty("received") Long received +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StatsInboundData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.received = received; + return builder; + } + + /** Builds a {@link StatsInboundData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long received; + + private Builder() { + } + + /** Sets {@code received}. */ + public Builder received(Long received) { + this.received = received; + return this; + } + + /** Sets {@code received}. */ + public Builder received(long received) { + this.received = received; + return this; + } + + /** Returns the {@link StatsInboundData}. */ + public StatsInboundData build() { + return new StatsInboundData(received); + } + } +} diff --git a/src/main/java/co/lettermint/types/StatsTotalsData.java b/src/main/java/co/lettermint/types/StatsTotalsData.java new file mode 100644 index 0000000..efe625a --- /dev/null +++ b/src/main/java/co/lettermint/types/StatsTotalsData.java @@ -0,0 +1,264 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param sent Always present. + * @param delivered Always present. + * @param hardBounced Always present. + * @param spamComplaints Always present. + * @param opened Null when tracking is not enabled for this context. Always present; may be null. + * @param clicked Null when tracking is not enabled for this context. Always present; may be null. + * @param inbound Always present. + * @param transactional Null for team-scoped stats (only available when project_id is specified). Always present; may be null. + * @param broadcast Null for team-scoped stats (only available when project_id is specified). Always present; may be null. + * @param observedOpened Human opens plus unresolved privacy-proxy opens. Optional and nullable: null when absent or null. + * @param humanOpened Optional and nullable: null when absent or null. + * @param privacyOpened Optional and nullable: null when absent or null. + * @param effectiveOpened Always present; may be null. + * @param machineOpened Always present; may be null. + * @param machineClicked Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StatsTotalsData( + @JsonProperty("sent") Long sent, + @JsonProperty("delivered") Long delivered, + @JsonProperty("hard_bounced") Long hardBounced, + @JsonProperty("spam_complaints") Long spamComplaints, + @JsonProperty("opened") Long opened, + @JsonProperty("clicked") Long clicked, + @JsonProperty("inbound") StatsInboundData inbound, + @JsonProperty("transactional") StatsTypeData transactional, + @JsonProperty("broadcast") StatsTypeData broadcast, + @JsonProperty("observed_opened") Long observedOpened, + @JsonProperty("human_opened") Long humanOpened, + @JsonProperty("privacy_opened") Long privacyOpened, + @JsonProperty("effective_opened") Long effectiveOpened, + @JsonProperty("machine_opened") Long machineOpened, + @JsonProperty("machine_clicked") Long machineClicked +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StatsTotalsData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.sent = sent; + builder.delivered = delivered; + builder.hardBounced = hardBounced; + builder.spamComplaints = spamComplaints; + builder.opened = opened; + builder.clicked = clicked; + builder.inbound = inbound; + builder.transactional = transactional; + builder.broadcast = broadcast; + builder.observedOpened = observedOpened; + builder.humanOpened = humanOpened; + builder.privacyOpened = privacyOpened; + builder.effectiveOpened = effectiveOpened; + builder.machineOpened = machineOpened; + builder.machineClicked = machineClicked; + return builder; + } + + /** Builds a {@link StatsTotalsData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long sent; + private Long delivered; + private Long hardBounced; + private Long spamComplaints; + private Long opened; + private Long clicked; + private StatsInboundData inbound; + private StatsTypeData transactional; + private StatsTypeData broadcast; + private Long observedOpened; + private Long humanOpened; + private Long privacyOpened; + private Long effectiveOpened; + private Long machineOpened; + private Long machineClicked; + + private Builder() { + } + + /** Sets {@code sent}. */ + public Builder sent(Long sent) { + this.sent = sent; + return this; + } + + /** Sets {@code sent}. */ + public Builder sent(long sent) { + this.sent = sent; + return this; + } + + /** Sets {@code delivered}. */ + public Builder delivered(Long delivered) { + this.delivered = delivered; + return this; + } + + /** Sets {@code delivered}. */ + public Builder delivered(long delivered) { + this.delivered = delivered; + return this; + } + + /** Sets {@code hard_bounced}. */ + public Builder hardBounced(Long hardBounced) { + this.hardBounced = hardBounced; + return this; + } + + /** Sets {@code hard_bounced}. */ + public Builder hardBounced(long hardBounced) { + this.hardBounced = hardBounced; + return this; + } + + /** Sets {@code spam_complaints}. */ + public Builder spamComplaints(Long spamComplaints) { + this.spamComplaints = spamComplaints; + return this; + } + + /** Sets {@code spam_complaints}. */ + public Builder spamComplaints(long spamComplaints) { + this.spamComplaints = spamComplaints; + return this; + } + + /** Sets {@code opened}. */ + public Builder opened(Long opened) { + this.opened = opened; + return this; + } + + /** Sets {@code opened}. */ + public Builder opened(long opened) { + this.opened = opened; + return this; + } + + /** Sets {@code clicked}. */ + public Builder clicked(Long clicked) { + this.clicked = clicked; + return this; + } + + /** Sets {@code clicked}. */ + public Builder clicked(long clicked) { + this.clicked = clicked; + return this; + } + + /** Sets {@code inbound}. */ + public Builder inbound(StatsInboundData inbound) { + this.inbound = inbound; + return this; + } + + /** Sets {@code transactional}. */ + public Builder transactional(StatsTypeData transactional) { + this.transactional = transactional; + return this; + } + + /** Sets {@code broadcast}. */ + public Builder broadcast(StatsTypeData broadcast) { + this.broadcast = broadcast; + return this; + } + + /** Sets {@code observed_opened}. */ + public Builder observedOpened(Long observedOpened) { + this.observedOpened = observedOpened; + return this; + } + + /** Sets {@code observed_opened}. */ + public Builder observedOpened(long observedOpened) { + this.observedOpened = observedOpened; + return this; + } + + /** Sets {@code human_opened}. */ + public Builder humanOpened(Long humanOpened) { + this.humanOpened = humanOpened; + return this; + } + + /** Sets {@code human_opened}. */ + public Builder humanOpened(long humanOpened) { + this.humanOpened = humanOpened; + return this; + } + + /** Sets {@code privacy_opened}. */ + public Builder privacyOpened(Long privacyOpened) { + this.privacyOpened = privacyOpened; + return this; + } + + /** Sets {@code privacy_opened}. */ + public Builder privacyOpened(long privacyOpened) { + this.privacyOpened = privacyOpened; + return this; + } + + /** Sets {@code effective_opened}. */ + public Builder effectiveOpened(Long effectiveOpened) { + this.effectiveOpened = effectiveOpened; + return this; + } + + /** Sets {@code effective_opened}. */ + public Builder effectiveOpened(long effectiveOpened) { + this.effectiveOpened = effectiveOpened; + return this; + } + + /** Sets {@code machine_opened}. */ + public Builder machineOpened(Long machineOpened) { + this.machineOpened = machineOpened; + return this; + } + + /** Sets {@code machine_opened}. */ + public Builder machineOpened(long machineOpened) { + this.machineOpened = machineOpened; + return this; + } + + /** Sets {@code machine_clicked}. */ + public Builder machineClicked(Long machineClicked) { + this.machineClicked = machineClicked; + return this; + } + + /** Sets {@code machine_clicked}. */ + public Builder machineClicked(long machineClicked) { + this.machineClicked = machineClicked; + return this; + } + + /** Returns the {@link StatsTotalsData}. */ + public StatsTotalsData build() { + return new StatsTotalsData(sent, delivered, hardBounced, spamComplaints, opened, clicked, inbound, transactional, broadcast, observedOpened, humanOpened, privacyOpened, effectiveOpened, machineOpened, machineClicked); + } + } +} diff --git a/src/main/java/co/lettermint/types/StatsTypeData.java b/src/main/java/co/lettermint/types/StatsTypeData.java new file mode 100644 index 0000000..d347f88 --- /dev/null +++ b/src/main/java/co/lettermint/types/StatsTypeData.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param sent Always present. + * @param hardBounced Always present. + * @param spamComplaints Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StatsTypeData( + @JsonProperty("sent") Long sent, + @JsonProperty("hard_bounced") Long hardBounced, + @JsonProperty("spam_complaints") Long spamComplaints +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StatsTypeData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.sent = sent; + builder.hardBounced = hardBounced; + builder.spamComplaints = spamComplaints; + return builder; + } + + /** Builds a {@link StatsTypeData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long sent; + private Long hardBounced; + private Long spamComplaints; + + private Builder() { + } + + /** Sets {@code sent}. */ + public Builder sent(Long sent) { + this.sent = sent; + return this; + } + + /** Sets {@code sent}. */ + public Builder sent(long sent) { + this.sent = sent; + return this; + } + + /** Sets {@code hard_bounced}. */ + public Builder hardBounced(Long hardBounced) { + this.hardBounced = hardBounced; + return this; + } + + /** Sets {@code hard_bounced}. */ + public Builder hardBounced(long hardBounced) { + this.hardBounced = hardBounced; + return this; + } + + /** Sets {@code spam_complaints}. */ + public Builder spamComplaints(Long spamComplaints) { + this.spamComplaints = spamComplaints; + return this; + } + + /** Sets {@code spam_complaints}. */ + public Builder spamComplaints(long spamComplaints) { + this.spamComplaints = spamComplaints; + return this; + } + + /** Returns the {@link StatsTypeData}. */ + public StatsTypeData build() { + return new StatsTypeData(sent, hardBounced, spamComplaints); + } + } +} diff --git a/src/main/java/co/lettermint/types/StoreDomainData.java b/src/main/java/co/lettermint/types/StoreDomainData.java new file mode 100644 index 0000000..955aa38 --- /dev/null +++ b/src/main/java/co/lettermint/types/StoreDomainData.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param domain Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StoreDomainData( + @JsonProperty("domain") String domain +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StoreDomainData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.domain = domain; + return builder; + } + + /** Builds a {@link StoreDomainData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String domain; + + private Builder() { + } + + /** Sets {@code domain}. */ + public Builder domain(String domain) { + this.domain = domain; + return this; + } + + /** Returns the {@link StoreDomainData}. */ + public StoreDomainData build() { + return new StoreDomainData(domain); + } + } +} diff --git a/src/main/java/co/lettermint/types/StoreProjectData.java b/src/main/java/co/lettermint/types/StoreProjectData.java new file mode 100644 index 0000000..029108b --- /dev/null +++ b/src/main/java/co/lettermint/types/StoreProjectData.java @@ -0,0 +1,102 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Required. + * @param smtpEnabled Optional: null omits it. + * @param deliveryMode Optional: null omits it. + * @param initialRoutes Optional: null omits it. + * @param shortToken Optional: null omits it. + * @param redactEmailContent Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StoreProjectData( + @JsonProperty("name") String name, + @JsonProperty("smtp_enabled") Boolean smtpEnabled, + @JsonProperty("delivery_mode") DeliveryMode deliveryMode, + @JsonProperty("initial_routes") InitialRoutes initialRoutes, + @JsonProperty("short_token") Boolean shortToken, + @JsonProperty("redact_email_content") Boolean redactEmailContent +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StoreProjectData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.smtpEnabled = smtpEnabled; + builder.deliveryMode = deliveryMode; + builder.initialRoutes = initialRoutes; + builder.shortToken = shortToken; + builder.redactEmailContent = redactEmailContent; + return builder; + } + + /** Builds a {@link StoreProjectData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private Boolean smtpEnabled; + private DeliveryMode deliveryMode; + private InitialRoutes initialRoutes; + private Boolean shortToken; + private Boolean redactEmailContent; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code smtp_enabled}. */ + public Builder smtpEnabled(Boolean smtpEnabled) { + this.smtpEnabled = smtpEnabled; + return this; + } + + /** Sets {@code delivery_mode}. */ + public Builder deliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = deliveryMode; + return this; + } + + /** Sets {@code initial_routes}. */ + public Builder initialRoutes(InitialRoutes initialRoutes) { + this.initialRoutes = initialRoutes; + return this; + } + + /** Sets {@code short_token}. */ + public Builder shortToken(Boolean shortToken) { + this.shortToken = shortToken; + return this; + } + + /** Sets {@code redact_email_content}. */ + public Builder redactEmailContent(Boolean redactEmailContent) { + this.redactEmailContent = redactEmailContent; + return this; + } + + /** Returns the {@link StoreProjectData}. */ + public StoreProjectData build() { + return new StoreProjectData(name, smtpEnabled, deliveryMode, initialRoutes, shortToken, redactEmailContent); + } + } +} diff --git a/src/main/java/co/lettermint/types/StoreRouteData.java b/src/main/java/co/lettermint/types/StoreRouteData.java new file mode 100644 index 0000000..a4bd8ff --- /dev/null +++ b/src/main/java/co/lettermint/types/StoreRouteData.java @@ -0,0 +1,128 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Required. + * @param routeType Required. + * @param slug Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param settings Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundSettings Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundDomain Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundSpamThreshold Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param attachmentDelivery Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StoreRouteData( + @JsonProperty("name") String name, + @JsonProperty("route_type") RouteType routeType, + @JsonProperty("slug") OptionalNullable slug, + @JsonProperty("settings") OptionalNullable settings, + @JsonProperty("inbound_settings") OptionalNullable inboundSettings, + @JsonProperty("inbound_domain") OptionalNullable inboundDomain, + @JsonProperty("inbound_spam_threshold") OptionalNullable inboundSpamThreshold, + @JsonProperty("attachment_delivery") OptionalNullable attachmentDelivery +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StoreRouteData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.routeType = routeType; + builder.slug = slug; + builder.settings = settings; + builder.inboundSettings = inboundSettings; + builder.inboundDomain = inboundDomain; + builder.inboundSpamThreshold = inboundSpamThreshold; + builder.attachmentDelivery = attachmentDelivery; + return builder; + } + + /** Builds a {@link StoreRouteData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private RouteType routeType; + private OptionalNullable slug; + private OptionalNullable settings; + private OptionalNullable inboundSettings; + private OptionalNullable inboundDomain; + private OptionalNullable inboundSpamThreshold; + private OptionalNullable attachmentDelivery; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code route_type}. */ + public Builder routeType(RouteType routeType) { + this.routeType = routeType; + return this; + } + + /** Sets {@code slug}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder slug(String slug) { + this.slug = OptionalNullable.of(slug); + return this; + } + + /** Sets {@code settings}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder settings(UpdateRouteSettingsData settings) { + this.settings = OptionalNullable.of(settings); + return this; + } + + /** Sets {@code inbound_settings}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundSettings(UpdateRouteInboundSettingsData inboundSettings) { + this.inboundSettings = OptionalNullable.of(inboundSettings); + return this; + } + + /** Sets {@code inbound_domain}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundDomain(String inboundDomain) { + this.inboundDomain = OptionalNullable.of(inboundDomain); + return this; + } + + /** Sets {@code inbound_spam_threshold}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundSpamThreshold(Double inboundSpamThreshold) { + this.inboundSpamThreshold = OptionalNullable.of(inboundSpamThreshold); + return this; + } + + /** Sets {@code inbound_spam_threshold}. */ + public Builder inboundSpamThreshold(double inboundSpamThreshold) { + this.inboundSpamThreshold = OptionalNullable.of(inboundSpamThreshold); + return this; + } + + /** Sets {@code attachment_delivery}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder attachmentDelivery(AttachmentDelivery attachmentDelivery) { + this.attachmentDelivery = OptionalNullable.of(attachmentDelivery); + return this; + } + + /** Returns the {@link StoreRouteData}. */ + public StoreRouteData build() { + return new StoreRouteData(name, routeType, slug, settings, inboundSettings, inboundDomain, inboundSpamThreshold, attachmentDelivery); + } + } +} diff --git a/src/main/java/co/lettermint/types/StoreSuppressionData.java b/src/main/java/co/lettermint/types/StoreSuppressionData.java new file mode 100644 index 0000000..19c829b --- /dev/null +++ b/src/main/java/co/lettermint/types/StoreSuppressionData.java @@ -0,0 +1,118 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param email Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param emails Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param reason Required. + * @param scope Required. + * @param routeId Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param projectId Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param appliesTo Mail category to block. Manual suppressions default to all. Use broadcast only at team scope, project scope, or on a broadcast route. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StoreSuppressionData( + @JsonProperty("email") OptionalNullable email, + @JsonProperty("emails") OptionalNullable> emails, + @JsonProperty("reason") SuppressionCreateReason reason, + @JsonProperty("scope") SuppressionCreateScope scope, + @JsonProperty("route_id") OptionalNullable routeId, + @JsonProperty("project_id") OptionalNullable projectId, + @JsonProperty("applies_to") OptionalNullable appliesTo +) { + /** Copies lists and maps into unmodifiable collections. */ + public StoreSuppressionData { + emails = emails == null || emails.isNull() ? emails : OptionalNullable.of(Copies.list(emails.value())); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StoreSuppressionData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.email = email; + builder.emails = emails; + builder.reason = reason; + builder.scope = scope; + builder.routeId = routeId; + builder.projectId = projectId; + builder.appliesTo = appliesTo; + return builder; + } + + /** Builds a {@link StoreSuppressionData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private OptionalNullable email; + private OptionalNullable> emails; + private SuppressionCreateReason reason; + private SuppressionCreateScope scope; + private OptionalNullable routeId; + private OptionalNullable projectId; + private OptionalNullable appliesTo; + + private Builder() { + } + + /** Sets {@code email}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder email(String email) { + this.email = OptionalNullable.of(email); + return this; + } + + /** Sets {@code emails}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder emails(List emails) { + this.emails = OptionalNullable.of(emails); + return this; + } + + /** Sets {@code reason}. */ + public Builder reason(SuppressionCreateReason reason) { + this.reason = reason; + return this; + } + + /** Sets {@code scope}. */ + public Builder scope(SuppressionCreateScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code route_id}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder routeId(String routeId) { + this.routeId = OptionalNullable.of(routeId); + return this; + } + + /** Sets {@code project_id}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder projectId(String projectId) { + this.projectId = OptionalNullable.of(projectId); + return this; + } + + /** Sets {@code applies_to}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder appliesTo(SuppressionAppliesTo appliesTo) { + this.appliesTo = OptionalNullable.of(appliesTo); + return this; + } + + /** Returns the {@link StoreSuppressionData}. */ + public StoreSuppressionData build() { + return new StoreSuppressionData(email, emails, reason, scope, routeId, projectId, appliesTo); + } + } +} diff --git a/src/main/java/co/lettermint/types/StoreWebhookData.java b/src/main/java/co/lettermint/types/StoreWebhookData.java new file mode 100644 index 0000000..9493489 --- /dev/null +++ b/src/main/java/co/lettermint/types/StoreWebhookData.java @@ -0,0 +1,160 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param name Required. + * @param url Required. + * @param events Required. + * @param enabled Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param includeMachineEvents Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param deliveryModeFilter Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param scope Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param projectIds Optional: null omits it. + * @param routeIds Optional: null omits it. + * @param routeId Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param basicAuth Write-only credentials. Omit to keep credentials. Null removes Basic Auth. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record StoreWebhookData( + @JsonProperty("name") String name, + @JsonProperty("url") String url, + @JsonProperty("events") List events, + @JsonProperty("enabled") OptionalNullable enabled, + @JsonProperty("include_machine_events") OptionalNullable includeMachineEvents, + @JsonProperty("delivery_mode_filter") OptionalNullable deliveryModeFilter, + @JsonProperty("scope") OptionalNullable scope, + @JsonProperty("project_ids") List projectIds, + @JsonProperty("route_ids") List routeIds, + @JsonProperty("route_id") OptionalNullable routeId, + @JsonProperty("basic_auth") OptionalNullable basicAuth +) { + /** Copies lists and maps into unmodifiable collections. */ + public StoreWebhookData { + events = Copies.list(events); + projectIds = Copies.list(projectIds); + routeIds = Copies.list(routeIds); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this StoreWebhookData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.url = url; + builder.events = events; + builder.enabled = enabled; + builder.includeMachineEvents = includeMachineEvents; + builder.deliveryModeFilter = deliveryModeFilter; + builder.scope = scope; + builder.projectIds = projectIds; + builder.routeIds = routeIds; + builder.routeId = routeId; + builder.basicAuth = basicAuth; + return builder; + } + + /** Builds a {@link StoreWebhookData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private String url; + private List events; + private OptionalNullable enabled; + private OptionalNullable includeMachineEvents; + private OptionalNullable deliveryModeFilter; + private OptionalNullable scope; + private List projectIds; + private List routeIds; + private OptionalNullable routeId; + private OptionalNullable basicAuth; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code url}. */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** Sets {@code events}. */ + public Builder events(List events) { + this.events = events; + return this; + } + + /** Sets {@code enabled}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder enabled(Boolean enabled) { + this.enabled = OptionalNullable.of(enabled); + return this; + } + + /** Sets {@code include_machine_events}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder includeMachineEvents(Boolean includeMachineEvents) { + this.includeMachineEvents = OptionalNullable.of(includeMachineEvents); + return this; + } + + /** Sets {@code delivery_mode_filter}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder deliveryModeFilter(WebhookDeliveryModeFilter deliveryModeFilter) { + this.deliveryModeFilter = OptionalNullable.of(deliveryModeFilter); + return this; + } + + /** Sets {@code scope}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder scope(WebhookScope scope) { + this.scope = OptionalNullable.of(scope); + return this; + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Sets {@code route_ids}. */ + public Builder routeIds(List routeIds) { + this.routeIds = routeIds; + return this; + } + + /** Sets {@code route_id}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder routeId(String routeId) { + this.routeId = OptionalNullable.of(routeId); + return this; + } + + /** Sets {@code basic_auth}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder basicAuth(WebhookBasicAuthData basicAuth) { + this.basicAuth = OptionalNullable.of(basicAuth); + return this; + } + + /** Returns the {@link StoreWebhookData}. */ + public StoreWebhookData build() { + return new StoreWebhookData(name, url, events, enabled, includeMachineEvents, deliveryModeFilter, scope, projectIds, routeIds, routeId, basicAuth); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressedRecipientData.java b/src/main/java/co/lettermint/types/SuppressedRecipientData.java new file mode 100644 index 0000000..ec856e9 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressedRecipientData.java @@ -0,0 +1,142 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param type Always present. + * @param value Always present. + * @param reason Always present. + * @param scope Always present. + * @param appliesTo Always present. + * @param projectId Always present; may be null. + * @param routeId Always present; may be null. + * @param sourceMessage Optional and nullable: null when absent or null. + * @param createdAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SuppressedRecipientData( + @JsonProperty("id") String id, + @JsonProperty("type") SuppressionType type, + @JsonProperty("value") String value, + @JsonProperty("reason") SuppressionReason reason, + @JsonProperty("scope") SuppressionScope scope, + @JsonProperty("applies_to") SuppressionAppliesTo appliesTo, + @JsonProperty("project_id") String projectId, + @JsonProperty("route_id") String routeId, + @JsonProperty("source_message") SuppressionSourceMessageData sourceMessage, + @JsonProperty("created_at") String createdAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SuppressedRecipientData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.type = type; + builder.value = value; + builder.reason = reason; + builder.scope = scope; + builder.appliesTo = appliesTo; + builder.projectId = projectId; + builder.routeId = routeId; + builder.sourceMessage = sourceMessage; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link SuppressedRecipientData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private SuppressionType type; + private String value; + private SuppressionReason reason; + private SuppressionScope scope; + private SuppressionAppliesTo appliesTo; + private String projectId; + private String routeId; + private SuppressionSourceMessageData sourceMessage; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code type}. */ + public Builder type(SuppressionType type) { + this.type = type; + return this; + } + + /** Sets {@code value}. */ + public Builder value(String value) { + this.value = value; + return this; + } + + /** Sets {@code reason}. */ + public Builder reason(SuppressionReason reason) { + this.reason = reason; + return this; + } + + /** Sets {@code scope}. */ + public Builder scope(SuppressionScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code applies_to}. */ + public Builder appliesTo(SuppressionAppliesTo appliesTo) { + this.appliesTo = appliesTo; + return this; + } + + /** Sets {@code project_id}. */ + public Builder projectId(String projectId) { + this.projectId = projectId; + return this; + } + + /** Sets {@code route_id}. */ + public Builder routeId(String routeId) { + this.routeId = routeId; + return this; + } + + /** Sets {@code source_message}. */ + public Builder sourceMessage(SuppressionSourceMessageData sourceMessage) { + this.sourceMessage = sourceMessage; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link SuppressedRecipientData}. */ + public SuppressedRecipientData build() { + return new SuppressedRecipientData(id, type, value, reason, scope, appliesTo, projectId, routeId, sourceMessage, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionAppliesTo.java b/src/main/java/co/lettermint/types/SuppressionAppliesTo.java new file mode 100644 index 0000000..4a2109b --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionAppliesTo.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Mail category blocked by the suppression. all blocks transactional and broadcast mail. broadcast blocks broadcast mail only. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class SuppressionAppliesTo { + /** {@code "all"} */ + public static final SuppressionAppliesTo ALL = new SuppressionAppliesTo("all"); + + /** {@code "broadcast"} */ + public static final SuppressionAppliesTo BROADCAST = new SuppressionAppliesTo("broadcast"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(ALL.value, ALL); + known.put(BROADCAST.value, BROADCAST); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionAppliesTo(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionAppliesTo of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionAppliesTo known = KNOWN.get(value); + return known != null ? known : new SuppressionAppliesTo(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionAppliesTo that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionCreateReason.java b/src/main/java/co/lettermint/types/SuppressionCreateReason.java new file mode 100644 index 0000000..c9c2b40 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionCreateReason.java @@ -0,0 +1,94 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Reason that the recipient is suppressed. The disposable_email reason is reserved for route policies. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class SuppressionCreateReason { + /** {@code "spam_complaint"} */ + public static final SuppressionCreateReason SPAM_COMPLAINT = new SuppressionCreateReason("spam_complaint"); + + /** {@code "hard_bounce"} */ + public static final SuppressionCreateReason HARD_BOUNCE = new SuppressionCreateReason("hard_bounce"); + + /** {@code "unsubscribe"} */ + public static final SuppressionCreateReason UNSUBSCRIBE = new SuppressionCreateReason("unsubscribe"); + + /** {@code "manual"} */ + public static final SuppressionCreateReason MANUAL = new SuppressionCreateReason("manual"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(SPAM_COMPLAINT.value, SPAM_COMPLAINT); + known.put(HARD_BOUNCE.value, HARD_BOUNCE); + known.put(UNSUBSCRIBE.value, UNSUBSCRIBE); + known.put(MANUAL.value, MANUAL); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionCreateReason(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionCreateReason of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionCreateReason known = KNOWN.get(value); + return known != null ? known : new SuppressionCreateReason(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionCreateReason that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionCreateScope.java b/src/main/java/co/lettermint/types/SuppressionCreateScope.java new file mode 100644 index 0000000..453084b --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionCreateScope.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Where the suppression applies. The global and subscription_group scopes cannot be created through the API. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class SuppressionCreateScope { + /** {@code "team"} */ + public static final SuppressionCreateScope TEAM = new SuppressionCreateScope("team"); + + /** {@code "project"} */ + public static final SuppressionCreateScope PROJECT = new SuppressionCreateScope("project"); + + /** {@code "route"} */ + public static final SuppressionCreateScope ROUTE = new SuppressionCreateScope("route"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TEAM.value, TEAM); + known.put(PROJECT.value, PROJECT); + known.put(ROUTE.value, ROUTE); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionCreateScope(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionCreateScope of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionCreateScope known = KNOWN.get(value); + return known != null ? known : new SuppressionCreateScope(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionCreateScope that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java b/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java new file mode 100644 index 0000000..b876a36 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java @@ -0,0 +1,90 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Confirmation that a suppression was removed. + * + * @param success Always present. + * @param status Always present. + * @param message Human-readable confirmation. Always present. + * @param confidence Confidence of the automated removal assessment, when one ran. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SuppressionDeletedResponse( + @JsonProperty("success") Boolean success, + @JsonProperty("status") String status, + @JsonProperty("message") String message, + @JsonProperty("confidence") Double confidence +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SuppressionDeletedResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.success = success; + builder.status = status; + builder.message = message; + builder.confidence = confidence; + return builder; + } + + /** Builds a {@link SuppressionDeletedResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean success; + private String status; + private String message; + private Double confidence; + + private Builder() { + } + + /** Sets {@code success}. */ + public Builder success(Boolean success) { + this.success = success; + return this; + } + + /** Sets {@code status}. */ + public Builder status(String status) { + this.status = status; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code confidence}. */ + public Builder confidence(Double confidence) { + this.confidence = confidence; + return this; + } + + /** Sets {@code confidence}. */ + public Builder confidence(double confidence) { + this.confidence = confidence; + return this; + } + + /** Returns the {@link SuppressionDeletedResponse}. */ + public SuppressionDeletedResponse build() { + return new SuppressionDeletedResponse(success, status, message, confidence); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionReason.java b/src/main/java/co/lettermint/types/SuppressionReason.java new file mode 100644 index 0000000..92fbd42 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionReason.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Reason that the recipient is suppressed. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class SuppressionReason { + /** {@code "spam_complaint"} */ + public static final SuppressionReason SPAM_COMPLAINT = new SuppressionReason("spam_complaint"); + + /** {@code "hard_bounce"} */ + public static final SuppressionReason HARD_BOUNCE = new SuppressionReason("hard_bounce"); + + /** {@code "unsubscribe"} */ + public static final SuppressionReason UNSUBSCRIBE = new SuppressionReason("unsubscribe"); + + /** {@code "manual"} */ + public static final SuppressionReason MANUAL = new SuppressionReason("manual"); + + /** {@code "disposable_email"} */ + public static final SuppressionReason DISPOSABLE_EMAIL = new SuppressionReason("disposable_email"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(SPAM_COMPLAINT.value, SPAM_COMPLAINT); + known.put(HARD_BOUNCE.value, HARD_BOUNCE); + known.put(UNSUBSCRIBE.value, UNSUBSCRIBE); + known.put(MANUAL.value, MANUAL); + known.put(DISPOSABLE_EMAIL.value, DISPOSABLE_EMAIL); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionReason(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionReason of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionReason known = KNOWN.get(value); + return known != null ? known : new SuppressionReason(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionReason that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionReviewResponse.java b/src/main/java/co/lettermint/types/SuppressionReviewResponse.java new file mode 100644 index 0000000..9351fc3 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionReviewResponse.java @@ -0,0 +1,100 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * A suppression that stays active while a support ticket reviews its removal. + * + * @param success Always present. + * @param status Always present. + * @param message Human-readable confirmation. Always present. + * @param ticketIdentifier The identifier of the support ticket that reviews the removal. Always present. + * @param confidence Confidence of the automated removal assessment, when one ran. Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SuppressionReviewResponse( + @JsonProperty("success") Boolean success, + @JsonProperty("status") SuppressionReviewResponseStatus status, + @JsonProperty("message") String message, + @JsonProperty("ticket_identifier") String ticketIdentifier, + @JsonProperty("confidence") Double confidence +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SuppressionReviewResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.success = success; + builder.status = status; + builder.message = message; + builder.ticketIdentifier = ticketIdentifier; + builder.confidence = confidence; + return builder; + } + + /** Builds a {@link SuppressionReviewResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Boolean success; + private SuppressionReviewResponseStatus status; + private String message; + private String ticketIdentifier; + private Double confidence; + + private Builder() { + } + + /** Sets {@code success}. */ + public Builder success(Boolean success) { + this.success = success; + return this; + } + + /** Sets {@code status}. */ + public Builder status(SuppressionReviewResponseStatus status) { + this.status = status; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code ticket_identifier}. */ + public Builder ticketIdentifier(String ticketIdentifier) { + this.ticketIdentifier = ticketIdentifier; + return this; + } + + /** Sets {@code confidence}. */ + public Builder confidence(Double confidence) { + this.confidence = confidence; + return this; + } + + /** Sets {@code confidence}. */ + public Builder confidence(double confidence) { + this.confidence = confidence; + return this; + } + + /** Returns the {@link SuppressionReviewResponse}. */ + public SuppressionReviewResponse build() { + return new SuppressionReviewResponse(success, status, message, ticketIdentifier, confidence); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java b/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java new file mode 100644 index 0000000..3c4b1bf --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class SuppressionReviewResponseStatus { + /** {@code "review_ticket_created"} */ + public static final SuppressionReviewResponseStatus REVIEW_TICKET_CREATED = new SuppressionReviewResponseStatus("review_ticket_created"); + + /** {@code "review_ticket_exists"} */ + public static final SuppressionReviewResponseStatus REVIEW_TICKET_EXISTS = new SuppressionReviewResponseStatus("review_ticket_exists"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(REVIEW_TICKET_CREATED.value, REVIEW_TICKET_CREATED); + known.put(REVIEW_TICKET_EXISTS.value, REVIEW_TICKET_EXISTS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionReviewResponseStatus(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionReviewResponseStatus of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionReviewResponseStatus known = KNOWN.get(value); + return known != null ? known : new SuppressionReviewResponseStatus(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionReviewResponseStatus that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionScope.java b/src/main/java/co/lettermint/types/SuppressionScope.java new file mode 100644 index 0000000..609dcaa --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionScope.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Where the suppression applies. + * + * An open enum: values that the API adds later decode as well and keep their raw value. + */ +public final class SuppressionScope { + /** {@code "global"} */ + public static final SuppressionScope GLOBAL = new SuppressionScope("global"); + + /** {@code "team"} */ + public static final SuppressionScope TEAM = new SuppressionScope("team"); + + /** {@code "project"} */ + public static final SuppressionScope PROJECT = new SuppressionScope("project"); + + /** {@code "route"} */ + public static final SuppressionScope ROUTE = new SuppressionScope("route"); + + /** {@code "subscription_group"} */ + public static final SuppressionScope SUBSCRIPTION_GROUP = new SuppressionScope("subscription_group"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(GLOBAL.value, GLOBAL); + known.put(TEAM.value, TEAM); + known.put(PROJECT.value, PROJECT); + known.put(ROUTE.value, ROUTE); + known.put(SUBSCRIPTION_GROUP.value, SUBSCRIPTION_GROUP); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionScope(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionScope of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionScope known = KNOWN.get(value); + return known != null ? known : new SuppressionScope(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionScope that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java b/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java new file mode 100644 index 0000000..63786f8 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param available Always present. + * @param subject Always present; may be null. + * @param createdAt Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SuppressionSourceMessageData( + @JsonProperty("id") String id, + @JsonProperty("available") Boolean available, + @JsonProperty("subject") String subject, + @JsonProperty("created_at") String createdAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SuppressionSourceMessageData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.available = available; + builder.subject = subject; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link SuppressionSourceMessageData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private Boolean available; + private String subject; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code available}. */ + public Builder available(Boolean available) { + this.available = available; + return this; + } + + /** Sets {@code subject}. */ + public Builder subject(String subject) { + this.subject = subject; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link SuppressionSourceMessageData}. */ + public SuppressionSourceMessageData build() { + return new SuppressionSourceMessageData(id, available, subject, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionStoreResponse.java b/src/main/java/co/lettermint/types/SuppressionStoreResponse.java new file mode 100644 index 0000000..8b87825 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionStoreResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The outcome of adding addresses to the suppression list. + * + * @param message Human-readable summary. Always present. + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SuppressionStoreResponse( + @JsonProperty("message") String message, + @JsonProperty("data") SuppressionStoreResult data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SuppressionStoreResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + builder.data = data; + return builder; + } + + /** Builds a {@link SuppressionStoreResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + private SuppressionStoreResult data; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code data}. */ + public Builder data(SuppressionStoreResult data) { + this.data = data; + return this; + } + + /** Returns the {@link SuppressionStoreResponse}. */ + public SuppressionStoreResponse build() { + return new SuppressionStoreResponse(message, data); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionStoreResult.java b/src/main/java/co/lettermint/types/SuppressionStoreResult.java new file mode 100644 index 0000000..4ff7fae --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionStoreResult.java @@ -0,0 +1,71 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * The addresses that were added and the addresses that were already suppressed. + * + * @param created Always present. + * @param skipped Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record SuppressionStoreResult( + @JsonProperty("created") List created, + @JsonProperty("skipped") List skipped +) { + /** Copies lists and maps into unmodifiable collections. */ + public SuppressionStoreResult { + created = Copies.list(created); + skipped = Copies.list(skipped); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this SuppressionStoreResult. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.created = created; + builder.skipped = skipped; + return builder; + } + + /** Builds a {@link SuppressionStoreResult}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List created; + private List skipped; + + private Builder() { + } + + /** Sets {@code created}. */ + public Builder created(List created) { + this.created = created; + return this; + } + + /** Sets {@code skipped}. */ + public Builder skipped(List skipped) { + this.skipped = skipped; + return this; + } + + /** Returns the {@link SuppressionStoreResult}. */ + public SuppressionStoreResult build() { + return new SuppressionStoreResult(created, skipped); + } + } +} diff --git a/src/main/java/co/lettermint/types/SuppressionType.java b/src/main/java/co/lettermint/types/SuppressionType.java new file mode 100644 index 0000000..a82c349 --- /dev/null +++ b/src/main/java/co/lettermint/types/SuppressionType.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class SuppressionType { + /** {@code "email"} */ + public static final SuppressionType EMAIL = new SuppressionType("email"); + + /** {@code "domain"} */ + public static final SuppressionType DOMAIN = new SuppressionType("domain"); + + /** {@code "extension"} */ + public static final SuppressionType EXTENSION = new SuppressionType("extension"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(EMAIL.value, EMAIL); + known.put(DOMAIN.value, DOMAIN); + known.put(EXTENSION.value, EXTENSION); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private SuppressionType(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static SuppressionType of(String value) { + Objects.requireNonNull(value, "value"); + SuppressionType known = KNOWN.get(value); + return known != null ? known : new SuppressionType(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof SuppressionType that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/TeamAddonData.java b/src/main/java/co/lettermint/types/TeamAddonData.java new file mode 100644 index 0000000..d4c1191 --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamAddonData.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param type Always present; may be null. + * @param expiresAt Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamAddonData( + @JsonProperty("type") String type, + @JsonProperty("expires_at") String expiresAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamAddonData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.type = type; + builder.expiresAt = expiresAt; + return builder; + } + + /** Builds a {@link TeamAddonData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String type; + private String expiresAt; + + private Builder() { + } + + /** Sets {@code type}. */ + public Builder type(String type) { + this.type = type; + return this; + } + + /** Sets {@code expires_at}. */ + public Builder expiresAt(String expiresAt) { + this.expiresAt = expiresAt; + return this; + } + + /** Returns the {@link TeamAddonData}. */ + public TeamAddonData build() { + return new TeamAddonData(type, expiresAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamData.java b/src/main/java/co/lettermint/types/TeamData.java new file mode 100644 index 0000000..e3a2e8c --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamData.java @@ -0,0 +1,222 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param name Always present. + * @param type Always present. + * @param plan Always present. + * @param includedVolume Number of emails included in the team's monthly plan. Always present. + * @param tier Deprecated alias for included_volume. Always present. + * @param verifiedAt Always present; may be null. + * @param features Optional: null when absent. + * @param addons Optional: null when absent. + * @param createdAt Always present. + * @param domainsCount Optional: null when absent. + * @param projectsCount Optional: null when absent. + * @param membersCount Optional: null when absent. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamData( + @JsonProperty("id") String id, + @JsonProperty("name") String name, + @JsonProperty("type") TeamType type, + @JsonProperty("plan") Plan plan, + @JsonProperty("included_volume") Long includedVolume, + @JsonProperty("tier") Long tier, + @JsonProperty("verified_at") String verifiedAt, + @JsonProperty("features") List features, + @JsonProperty("addons") List addons, + @JsonProperty("created_at") String createdAt, + @JsonProperty("domains_count") Long domainsCount, + @JsonProperty("projects_count") Long projectsCount, + @JsonProperty("members_count") Long membersCount +) { + /** Copies lists and maps into unmodifiable collections. */ + public TeamData { + features = Copies.list(features); + addons = Copies.list(addons); + } + + /** + * Deprecated alias for included_volume + * + * @return {@code tier} + * @deprecated Deprecated by the API. + */ + @Deprecated + public Long tier() { + return tier; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + builder.type = type; + builder.plan = plan; + builder.includedVolume = includedVolume; + builder.tier = tier; + builder.verifiedAt = verifiedAt; + builder.features = features; + builder.addons = addons; + builder.createdAt = createdAt; + builder.domainsCount = domainsCount; + builder.projectsCount = projectsCount; + builder.membersCount = membersCount; + return builder; + } + + /** Builds a {@link TeamData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + private TeamType type; + private Plan plan; + private Long includedVolume; + private Long tier; + private String verifiedAt; + private List features; + private List addons; + private String createdAt; + private Long domainsCount; + private Long projectsCount; + private Long membersCount; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code type}. */ + public Builder type(TeamType type) { + this.type = type; + return this; + } + + /** Sets {@code plan}. */ + public Builder plan(Plan plan) { + this.plan = plan; + return this; + } + + /** Sets {@code included_volume}. */ + public Builder includedVolume(Long includedVolume) { + this.includedVolume = includedVolume; + return this; + } + + /** Sets {@code included_volume}. */ + public Builder includedVolume(long includedVolume) { + this.includedVolume = includedVolume; + return this; + } + + /** Sets {@code tier}. */ + @Deprecated + public Builder tier(Long tier) { + this.tier = tier; + return this; + } + + /** Sets {@code tier}. */ + @Deprecated + public Builder tier(long tier) { + this.tier = tier; + return this; + } + + /** Sets {@code verified_at}. */ + public Builder verifiedAt(String verifiedAt) { + this.verifiedAt = verifiedAt; + return this; + } + + /** Sets {@code features}. */ + public Builder features(List features) { + this.features = features; + return this; + } + + /** Sets {@code addons}. */ + public Builder addons(List addons) { + this.addons = addons; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code domains_count}. */ + public Builder domainsCount(Long domainsCount) { + this.domainsCount = domainsCount; + return this; + } + + /** Sets {@code domains_count}. */ + public Builder domainsCount(long domainsCount) { + this.domainsCount = domainsCount; + return this; + } + + /** Sets {@code projects_count}. */ + public Builder projectsCount(Long projectsCount) { + this.projectsCount = projectsCount; + return this; + } + + /** Sets {@code projects_count}. */ + public Builder projectsCount(long projectsCount) { + this.projectsCount = projectsCount; + return this; + } + + /** Sets {@code members_count}. */ + public Builder membersCount(Long membersCount) { + this.membersCount = membersCount; + return this; + } + + /** Sets {@code members_count}. */ + public Builder membersCount(long membersCount) { + this.membersCount = membersCount; + return this; + } + + /** Returns the {@link TeamData}. */ + public TeamData build() { + return new TeamData(id, name, type, plan, includedVolume, tier, verifiedAt, features, addons, createdAt, domainsCount, projectsCount, membersCount); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamMemberData.java b/src/main/java/co/lettermint/types/TeamMemberData.java new file mode 100644 index 0000000..073072d --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamMemberData.java @@ -0,0 +1,102 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param name Always present. + * @param email Always present. + * @param role Always present. + * @param projectAccess Always present. + * @param joinedAt Always present; may be null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamMemberData( + @JsonProperty("id") String id, + @JsonProperty("name") String name, + @JsonProperty("email") String email, + @JsonProperty("role") TeamMemberDataRole role, + @JsonProperty("project_access") TeamMemberProjectAccessData projectAccess, + @JsonProperty("joined_at") String joinedAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamMemberData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + builder.email = email; + builder.role = role; + builder.projectAccess = projectAccess; + builder.joinedAt = joinedAt; + return builder; + } + + /** Builds a {@link TeamMemberData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + private String email; + private TeamMemberDataRole role; + private TeamMemberProjectAccessData projectAccess; + private String joinedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code email}. */ + public Builder email(String email) { + this.email = email; + return this; + } + + /** Sets {@code role}. */ + public Builder role(TeamMemberDataRole role) { + this.role = role; + return this; + } + + /** Sets {@code project_access}. */ + public Builder projectAccess(TeamMemberProjectAccessData projectAccess) { + this.projectAccess = projectAccess; + return this; + } + + /** Sets {@code joined_at}. */ + public Builder joinedAt(String joinedAt) { + this.joinedAt = joinedAt; + return this; + } + + /** Returns the {@link TeamMemberData}. */ + public TeamMemberData build() { + return new TeamMemberData(id, name, email, role, projectAccess, joinedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamMemberDataRole.java b/src/main/java/co/lettermint/types/TeamMemberDataRole.java new file mode 100644 index 0000000..db971bc --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamMemberDataRole.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param name Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamMemberDataRole( + @JsonProperty("id") String id, + @JsonProperty("name") String name +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamMemberDataRole. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + return builder; + } + + /** Builds a {@link TeamMemberDataRole}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Returns the {@link TeamMemberDataRole}. */ + public TeamMemberDataRole build() { + return new TeamMemberDataRole(id, name); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java b/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java new file mode 100644 index 0000000..e20603c --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java @@ -0,0 +1,68 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param scope Always present. + * @param projects Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamMemberProjectAccessData( + @JsonProperty("scope") ProjectAccessScope scope, + @JsonProperty("projects") List projects +) { + /** Copies lists and maps into unmodifiable collections. */ + public TeamMemberProjectAccessData { + projects = Copies.list(projects); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamMemberProjectAccessData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.scope = scope; + builder.projects = projects; + return builder; + } + + /** Builds a {@link TeamMemberProjectAccessData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProjectAccessScope scope; + private List projects; + + private Builder() { + } + + /** Sets {@code scope}. */ + public Builder scope(ProjectAccessScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code projects}. */ + public Builder projects(List projects) { + this.projects = projects; + return this; + } + + /** Returns the {@link TeamMemberProjectAccessData}. */ + public TeamMemberProjectAccessData build() { + return new TeamMemberProjectAccessData(scope, projects); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java b/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java new file mode 100644 index 0000000..fdf6994 --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param name Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamMemberProjectAccessDataProjectsItem( + @JsonProperty("id") String id, + @JsonProperty("name") String name +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamMemberProjectAccessDataProjectsItem. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + return builder; + } + + /** Builds a {@link TeamMemberProjectAccessDataProjectsItem}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Returns the {@link TeamMemberProjectAccessDataProjectsItem}. */ + public TeamMemberProjectAccessDataProjectsItem build() { + return new TeamMemberProjectAccessDataProjectsItem(id, name); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamMutationResponse.java b/src/main/java/co/lettermint/types/TeamMutationResponse.java new file mode 100644 index 0000000..21b7051 --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamMutationResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The team after a settings change, with a confirmation message. + * + * @param data Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamMutationResponse( + @JsonProperty("data") TeamData data, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamMutationResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + return builder; + } + + /** Builds a {@link TeamMutationResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private TeamData data; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(TeamData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link TeamMutationResponse}. */ + public TeamMutationResponse build() { + return new TeamMutationResponse(data, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamRoleData.java b/src/main/java/co/lettermint/types/TeamRoleData.java new file mode 100644 index 0000000..087500b --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamRoleData.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param name Always present. + * @param systemKey Always present; may be null. + * @param permissions Always present. + * @param assignable Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamRoleData( + @JsonProperty("id") String id, + @JsonProperty("name") String name, + @JsonProperty("system_key") BuiltInTeamRole systemKey, + @JsonProperty("permissions") List permissions, + @JsonProperty("assignable") Boolean assignable +) { + /** Copies lists and maps into unmodifiable collections. */ + public TeamRoleData { + permissions = Copies.list(permissions); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamRoleData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.name = name; + builder.systemKey = systemKey; + builder.permissions = permissions; + builder.assignable = assignable; + return builder; + } + + /** Builds a {@link TeamRoleData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String name; + private BuiltInTeamRole systemKey; + private List permissions; + private Boolean assignable; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code system_key}. */ + public Builder systemKey(BuiltInTeamRole systemKey) { + this.systemKey = systemKey; + return this; + } + + /** Sets {@code permissions}. */ + public Builder permissions(List permissions) { + this.permissions = permissions; + return this; + } + + /** Sets {@code assignable}. */ + public Builder assignable(Boolean assignable) { + this.assignable = assignable; + return this; + } + + /** Returns the {@link TeamRoleData}. */ + public TeamRoleData build() { + return new TeamRoleData(id, name, systemKey, permissions, assignable); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamRoleListResponse.java b/src/main/java/co/lettermint/types/TeamRoleListResponse.java new file mode 100644 index 0000000..e131bf8 --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamRoleListResponse.java @@ -0,0 +1,60 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * The reusable roles of the team. + * + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamRoleListResponse( + @JsonProperty("data") List data +) { + /** Copies lists and maps into unmodifiable collections. */ + public TeamRoleListResponse { + data = Copies.list(data); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamRoleListResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link TeamRoleListResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(List data) { + this.data = data; + return this; + } + + /** Returns the {@link TeamRoleListResponse}. */ + public TeamRoleListResponse build() { + return new TeamRoleListResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamType.java b/src/main/java/co/lettermint/types/TeamType.java new file mode 100644 index 0000000..deec81c --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamType.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class TeamType { + /** {@code "personal"} */ + public static final TeamType PERSONAL = new TeamType("personal"); + + /** {@code "business"} */ + public static final TeamType BUSINESS = new TeamType("business"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PERSONAL.value, PERSONAL); + known.put(BUSINESS.value, BUSINESS); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private TeamType(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static TeamType of(String value) { + Objects.requireNonNull(value, "value"); + TeamType known = KNOWN.get(value); + return known != null ? known : new TeamType(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof TeamType that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/TeamUsageDetailData.java b/src/main/java/co/lettermint/types/TeamUsageDetailData.java new file mode 100644 index 0000000..3b0fcf9 --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamUsageDetailData.java @@ -0,0 +1,68 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param currentPeriod Always present. + * @param historicalUsage Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamUsageDetailData( + @JsonProperty("current_period") TeamUsagePeriodData currentPeriod, + @JsonProperty("historical_usage") List historicalUsage +) { + /** Copies lists and maps into unmodifiable collections. */ + public TeamUsageDetailData { + historicalUsage = Copies.list(historicalUsage); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamUsageDetailData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.currentPeriod = currentPeriod; + builder.historicalUsage = historicalUsage; + return builder; + } + + /** Builds a {@link TeamUsageDetailData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private TeamUsagePeriodData currentPeriod; + private List historicalUsage; + + private Builder() { + } + + /** Sets {@code current_period}. */ + public Builder currentPeriod(TeamUsagePeriodData currentPeriod) { + this.currentPeriod = currentPeriod; + return this; + } + + /** Sets {@code historical_usage}. */ + public Builder historicalUsage(List historicalUsage) { + this.historicalUsage = historicalUsage; + return this; + } + + /** Returns the {@link TeamUsageDetailData}. */ + public TeamUsageDetailData build() { + return new TeamUsageDetailData(currentPeriod, historicalUsage); + } + } +} diff --git a/src/main/java/co/lettermint/types/TeamUsagePeriodData.java b/src/main/java/co/lettermint/types/TeamUsagePeriodData.java new file mode 100644 index 0000000..a903edb --- /dev/null +++ b/src/main/java/co/lettermint/types/TeamUsagePeriodData.java @@ -0,0 +1,88 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param usage Always present. + * @param lastIncrementedAt Always present; may be null. + * @param periodStart Always present. + * @param periodEnd Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TeamUsagePeriodData( + @JsonProperty("usage") Long usage, + @JsonProperty("last_incremented_at") String lastIncrementedAt, + @JsonProperty("period_start") String periodStart, + @JsonProperty("period_end") String periodEnd +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TeamUsagePeriodData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.usage = usage; + builder.lastIncrementedAt = lastIncrementedAt; + builder.periodStart = periodStart; + builder.periodEnd = periodEnd; + return builder; + } + + /** Builds a {@link TeamUsagePeriodData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private Long usage; + private String lastIncrementedAt; + private String periodStart; + private String periodEnd; + + private Builder() { + } + + /** Sets {@code usage}. */ + public Builder usage(Long usage) { + this.usage = usage; + return this; + } + + /** Sets {@code usage}. */ + public Builder usage(long usage) { + this.usage = usage; + return this; + } + + /** Sets {@code last_incremented_at}. */ + public Builder lastIncrementedAt(String lastIncrementedAt) { + this.lastIncrementedAt = lastIncrementedAt; + return this; + } + + /** Sets {@code period_start}. */ + public Builder periodStart(String periodStart) { + this.periodStart = periodStart; + return this; + } + + /** Sets {@code period_end}. */ + public Builder periodEnd(String periodEnd) { + this.periodEnd = periodEnd; + return this; + } + + /** Returns the {@link TeamUsagePeriodData}. */ + public TeamUsagePeriodData build() { + return new TeamUsagePeriodData(usage, lastIncrementedAt, periodStart, periodEnd); + } + } +} diff --git a/src/main/java/co/lettermint/types/TestWebhookResponse.java b/src/main/java/co/lettermint/types/TestWebhookResponse.java new file mode 100644 index 0000000..0410529 --- /dev/null +++ b/src/main/java/co/lettermint/types/TestWebhookResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * Confirmation that a test delivery was queued. + * + * @param message Human-readable confirmation. Always present. + * @param deliveryId The ID of the queued test delivery. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record TestWebhookResponse( + @JsonProperty("message") String message, + @JsonProperty("delivery_id") String deliveryId +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this TestWebhookResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + builder.deliveryId = deliveryId; + return builder; + } + + /** Builds a {@link TestWebhookResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + private String deliveryId; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code delivery_id}. */ + public Builder deliveryId(String deliveryId) { + this.deliveryId = deliveryId; + return this; + } + + /** Returns the {@link TestWebhookResponse}. */ + public TestWebhookResponse build() { + return new TestWebhookResponse(message, deliveryId); + } + } +} diff --git a/src/main/java/co/lettermint/types/TlsPolicy.java b/src/main/java/co/lettermint/types/TlsPolicy.java new file mode 100644 index 0000000..94be5af --- /dev/null +++ b/src/main/java/co/lettermint/types/TlsPolicy.java @@ -0,0 +1,82 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class TlsPolicy { + /** {@code "opportunistic"} */ + public static final TlsPolicy OPPORTUNISTIC = new TlsPolicy("opportunistic"); + + /** {@code "enforced"} */ + public static final TlsPolicy ENFORCED = new TlsPolicy("enforced"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(OPPORTUNISTIC.value, OPPORTUNISTIC); + known.put(ENFORCED.value, ENFORCED); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private TlsPolicy(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static TlsPolicy of(String value) { + Objects.requireNonNull(value, "value"); + TlsPolicy known = KNOWN.get(value); + return known != null ? known : new TlsPolicy(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof TlsPolicy that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java b/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java new file mode 100644 index 0000000..93a163c --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java @@ -0,0 +1,58 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param projectIds Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateDomainProjectsData( + @JsonProperty("project_ids") List projectIds +) { + /** Copies lists and maps into unmodifiable collections. */ + public UpdateDomainProjectsData { + projectIds = Copies.list(projectIds); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateDomainProjectsData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.projectIds = projectIds; + return builder; + } + + /** Builds a {@link UpdateDomainProjectsData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private List projectIds; + + private Builder() { + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Returns the {@link UpdateDomainProjectsData}. */ + public UpdateDomainProjectsData build() { + return new UpdateDomainProjectsData(projectIds); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateProjectData.java b/src/main/java/co/lettermint/types/UpdateProjectData.java new file mode 100644 index 0000000..351b2a0 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateProjectData.java @@ -0,0 +1,92 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param smtpEnabled Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param redactEmailContent Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param deliveryMode Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param defaultRouteId Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateProjectData( + @JsonProperty("name") OptionalNullable name, + @JsonProperty("smtp_enabled") OptionalNullable smtpEnabled, + @JsonProperty("redact_email_content") OptionalNullable redactEmailContent, + @JsonProperty("delivery_mode") OptionalNullable deliveryMode, + @JsonProperty("default_route_id") OptionalNullable defaultRouteId +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateProjectData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.smtpEnabled = smtpEnabled; + builder.redactEmailContent = redactEmailContent; + builder.deliveryMode = deliveryMode; + builder.defaultRouteId = defaultRouteId; + return builder; + } + + /** Builds a {@link UpdateProjectData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private OptionalNullable name; + private OptionalNullable smtpEnabled; + private OptionalNullable redactEmailContent; + private OptionalNullable deliveryMode; + private OptionalNullable defaultRouteId; + + private Builder() { + } + + /** Sets {@code name}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder name(String name) { + this.name = OptionalNullable.of(name); + return this; + } + + /** Sets {@code smtp_enabled}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder smtpEnabled(Boolean smtpEnabled) { + this.smtpEnabled = OptionalNullable.of(smtpEnabled); + return this; + } + + /** Sets {@code redact_email_content}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder redactEmailContent(Boolean redactEmailContent) { + this.redactEmailContent = OptionalNullable.of(redactEmailContent); + return this; + } + + /** Sets {@code delivery_mode}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder deliveryMode(DeliveryMode deliveryMode) { + this.deliveryMode = OptionalNullable.of(deliveryMode); + return this; + } + + /** Sets {@code default_route_id}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder defaultRouteId(String defaultRouteId) { + this.defaultRouteId = OptionalNullable.of(defaultRouteId); + return this; + } + + /** Returns the {@link UpdateProjectData}. */ + public UpdateProjectData build() { + return new UpdateProjectData(name, smtpEnabled, redactEmailContent, deliveryMode, defaultRouteId); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java b/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java new file mode 100644 index 0000000..eb03d33 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateReportForwardingResponse( + @JsonProperty("data") ReportForwardingResource data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateReportForwardingResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link UpdateReportForwardingResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ReportForwardingResource data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ReportForwardingResource data) { + this.data = data; + return this; + } + + /** Returns the {@link UpdateReportForwardingResponse}. */ + public UpdateReportForwardingResponse build() { + return new UpdateReportForwardingResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateRouteData.java b/src/main/java/co/lettermint/types/UpdateRouteData.java new file mode 100644 index 0000000..a6c5633 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateRouteData.java @@ -0,0 +1,108 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param settings Route settings. track_opens and track_clicks apply to transactional and broadcast routes when email tracking is available. generate_plaintext_fallback opts in to generated plaintext fallbacks for HTML-only outbound messages; customer-provided plaintext is always preserved. suppress_auto_responders adds outbound headers that suppress auto-responders. suppress_disposable_recipients skips matching recipients for each message without adding them to suppression lists. tls controls whether TLS is opportunistic or enforced. disable_hosted_unsubscribe applies to broadcast routes when enabled for the team. redact_email_content requires email redaction access. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundSettings Inbound route settings. Only accepted for inbound routes. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundDomain Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundSpamThreshold Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param attachmentDelivery Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateRouteData( + @JsonProperty("name") OptionalNullable name, + @JsonProperty("settings") OptionalNullable settings, + @JsonProperty("inbound_settings") OptionalNullable inboundSettings, + @JsonProperty("inbound_domain") OptionalNullable inboundDomain, + @JsonProperty("inbound_spam_threshold") OptionalNullable inboundSpamThreshold, + @JsonProperty("attachment_delivery") OptionalNullable attachmentDelivery +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateRouteData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.settings = settings; + builder.inboundSettings = inboundSettings; + builder.inboundDomain = inboundDomain; + builder.inboundSpamThreshold = inboundSpamThreshold; + builder.attachmentDelivery = attachmentDelivery; + return builder; + } + + /** Builds a {@link UpdateRouteData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private OptionalNullable name; + private OptionalNullable settings; + private OptionalNullable inboundSettings; + private OptionalNullable inboundDomain; + private OptionalNullable inboundSpamThreshold; + private OptionalNullable attachmentDelivery; + + private Builder() { + } + + /** Sets {@code name}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder name(String name) { + this.name = OptionalNullable.of(name); + return this; + } + + /** Sets {@code settings}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder settings(UpdateRouteSettingsData settings) { + this.settings = OptionalNullable.of(settings); + return this; + } + + /** Sets {@code inbound_settings}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundSettings(UpdateRouteInboundSettingsData inboundSettings) { + this.inboundSettings = OptionalNullable.of(inboundSettings); + return this; + } + + /** Sets {@code inbound_domain}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundDomain(String inboundDomain) { + this.inboundDomain = OptionalNullable.of(inboundDomain); + return this; + } + + /** Sets {@code inbound_spam_threshold}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundSpamThreshold(Double inboundSpamThreshold) { + this.inboundSpamThreshold = OptionalNullable.of(inboundSpamThreshold); + return this; + } + + /** Sets {@code inbound_spam_threshold}. */ + public Builder inboundSpamThreshold(double inboundSpamThreshold) { + this.inboundSpamThreshold = OptionalNullable.of(inboundSpamThreshold); + return this; + } + + /** Sets {@code attachment_delivery}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder attachmentDelivery(AttachmentDelivery attachmentDelivery) { + this.attachmentDelivery = OptionalNullable.of(attachmentDelivery); + return this; + } + + /** Returns the {@link UpdateRouteData}. */ + public UpdateRouteData build() { + return new UpdateRouteData(name, settings, inboundSettings, inboundDomain, inboundSpamThreshold, attachmentDelivery); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java b/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java new file mode 100644 index 0000000..dc4a225 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java @@ -0,0 +1,78 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param inboundDomain Custom receiving domain for inbound routes, such as support.example.com or *.m.example.com. Address patterns such as *@*.m.example.com are normalized. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param inboundSpamThreshold Inbound spam threshold for inbound routes. Higher values are more permissive. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param attachmentDelivery Inbound attachment delivery mode. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateRouteInboundSettingsData( + @JsonProperty("inbound_domain") OptionalNullable inboundDomain, + @JsonProperty("inbound_spam_threshold") OptionalNullable inboundSpamThreshold, + @JsonProperty("attachment_delivery") OptionalNullable attachmentDelivery +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateRouteInboundSettingsData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.inboundDomain = inboundDomain; + builder.inboundSpamThreshold = inboundSpamThreshold; + builder.attachmentDelivery = attachmentDelivery; + return builder; + } + + /** Builds a {@link UpdateRouteInboundSettingsData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private OptionalNullable inboundDomain; + private OptionalNullable inboundSpamThreshold; + private OptionalNullable attachmentDelivery; + + private Builder() { + } + + /** Sets {@code inbound_domain}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundDomain(String inboundDomain) { + this.inboundDomain = OptionalNullable.of(inboundDomain); + return this; + } + + /** Sets {@code inbound_spam_threshold}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder inboundSpamThreshold(Double inboundSpamThreshold) { + this.inboundSpamThreshold = OptionalNullable.of(inboundSpamThreshold); + return this; + } + + /** Sets {@code inbound_spam_threshold}. */ + public Builder inboundSpamThreshold(double inboundSpamThreshold) { + this.inboundSpamThreshold = OptionalNullable.of(inboundSpamThreshold); + return this; + } + + /** Sets {@code attachment_delivery}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder attachmentDelivery(AttachmentDelivery attachmentDelivery) { + this.attachmentDelivery = OptionalNullable.of(attachmentDelivery); + return this; + } + + /** Returns the {@link UpdateRouteInboundSettingsData}. */ + public UpdateRouteInboundSettingsData build() { + return new UpdateRouteInboundSettingsData(inboundDomain, inboundSpamThreshold, attachmentDelivery); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java b/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java new file mode 100644 index 0000000..6cad7e7 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java @@ -0,0 +1,122 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param trackOpens Enable open tracking for transactional and broadcast routes. Requires email tracking access. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param trackClicks Enable click tracking for transactional and broadcast routes. Requires email tracking access. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param generatePlaintextFallback Opt in to generated plaintext fallbacks for HTML-only outbound messages on transactional and broadcast routes. Customer-provided plaintext is always preserved. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param suppressAutoResponders Add outbound headers that suppress auto-responders for transactional and broadcast routes. Customer-provided header values are preserved. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param suppressDisposableRecipients Skip disposable email recipients for transactional and broadcast routes. This check applies to each message and does not add recipients to suppression lists. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param tls TLS delivery policy for transactional and broadcast routes. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param disableHostedUnsubscribe Disable Lettermint-hosted unsubscribe link injection for broadcast routes. Available only when enabled for the team. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param redactEmailContent Redact email content in the dashboard for this route. Requires email redaction access. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateRouteSettingsData( + @JsonProperty("track_opens") OptionalNullable trackOpens, + @JsonProperty("track_clicks") OptionalNullable trackClicks, + @JsonProperty("generate_plaintext_fallback") OptionalNullable generatePlaintextFallback, + @JsonProperty("suppress_auto_responders") OptionalNullable suppressAutoResponders, + @JsonProperty("suppress_disposable_recipients") OptionalNullable suppressDisposableRecipients, + @JsonProperty("tls") OptionalNullable tls, + @JsonProperty("disable_hosted_unsubscribe") OptionalNullable disableHostedUnsubscribe, + @JsonProperty("redact_email_content") OptionalNullable redactEmailContent +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateRouteSettingsData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.trackOpens = trackOpens; + builder.trackClicks = trackClicks; + builder.generatePlaintextFallback = generatePlaintextFallback; + builder.suppressAutoResponders = suppressAutoResponders; + builder.suppressDisposableRecipients = suppressDisposableRecipients; + builder.tls = tls; + builder.disableHostedUnsubscribe = disableHostedUnsubscribe; + builder.redactEmailContent = redactEmailContent; + return builder; + } + + /** Builds a {@link UpdateRouteSettingsData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private OptionalNullable trackOpens; + private OptionalNullable trackClicks; + private OptionalNullable generatePlaintextFallback; + private OptionalNullable suppressAutoResponders; + private OptionalNullable suppressDisposableRecipients; + private OptionalNullable tls; + private OptionalNullable disableHostedUnsubscribe; + private OptionalNullable redactEmailContent; + + private Builder() { + } + + /** Sets {@code track_opens}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder trackOpens(Boolean trackOpens) { + this.trackOpens = OptionalNullable.of(trackOpens); + return this; + } + + /** Sets {@code track_clicks}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder trackClicks(Boolean trackClicks) { + this.trackClicks = OptionalNullable.of(trackClicks); + return this; + } + + /** Sets {@code generate_plaintext_fallback}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder generatePlaintextFallback(Boolean generatePlaintextFallback) { + this.generatePlaintextFallback = OptionalNullable.of(generatePlaintextFallback); + return this; + } + + /** Sets {@code suppress_auto_responders}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder suppressAutoResponders(Boolean suppressAutoResponders) { + this.suppressAutoResponders = OptionalNullable.of(suppressAutoResponders); + return this; + } + + /** Sets {@code suppress_disposable_recipients}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder suppressDisposableRecipients(Boolean suppressDisposableRecipients) { + this.suppressDisposableRecipients = OptionalNullable.of(suppressDisposableRecipients); + return this; + } + + /** Sets {@code tls}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder tls(TlsPolicy tls) { + this.tls = OptionalNullable.of(tls); + return this; + } + + /** Sets {@code disable_hosted_unsubscribe}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder disableHostedUnsubscribe(Boolean disableHostedUnsubscribe) { + this.disableHostedUnsubscribe = OptionalNullable.of(disableHostedUnsubscribe); + return this; + } + + /** Sets {@code redact_email_content}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder redactEmailContent(Boolean redactEmailContent) { + this.redactEmailContent = OptionalNullable.of(redactEmailContent); + return this; + } + + /** Returns the {@link UpdateRouteSettingsData}. */ + public UpdateRouteSettingsData build() { + return new UpdateRouteSettingsData(trackOpens, trackClicks, generatePlaintextFallback, suppressAutoResponders, suppressDisposableRecipients, tls, disableHostedUnsubscribe, redactEmailContent); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateTeamData.java b/src/main/java/co/lettermint/types/UpdateTeamData.java new file mode 100644 index 0000000..a8a67f4 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateTeamData.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param name Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateTeamData( + @JsonProperty("name") String name +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateTeamData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + return builder; + } + + /** Builds a {@link UpdateTeamData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Returns the {@link UpdateTeamData}. */ + public UpdateTeamData build() { + return new UpdateTeamData(name); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java new file mode 100644 index 0000000..3260355 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java @@ -0,0 +1,62 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param roleId Required. + * @param projectAccess Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateTeamMemberAssignmentData( + @JsonProperty("role_id") String roleId, + @JsonProperty("project_access") UpdateTeamMemberAssignmentDataProjectAccess projectAccess +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateTeamMemberAssignmentData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.roleId = roleId; + builder.projectAccess = projectAccess; + return builder; + } + + /** Builds a {@link UpdateTeamMemberAssignmentData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String roleId; + private UpdateTeamMemberAssignmentDataProjectAccess projectAccess; + + private Builder() { + } + + /** Sets {@code role_id}. */ + public Builder roleId(String roleId) { + this.roleId = roleId; + return this; + } + + /** Sets {@code project_access}. */ + public Builder projectAccess(UpdateTeamMemberAssignmentDataProjectAccess projectAccess) { + this.projectAccess = projectAccess; + return this; + } + + /** Returns the {@link UpdateTeamMemberAssignmentData}. */ + public UpdateTeamMemberAssignmentData build() { + return new UpdateTeamMemberAssignmentData(roleId, projectAccess); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java new file mode 100644 index 0000000..7b6a153 --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java @@ -0,0 +1,68 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param scope Required. + * @param projectIds Optional: null omits it. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateTeamMemberAssignmentDataProjectAccess( + @JsonProperty("scope") ProjectAccessScope scope, + @JsonProperty("project_ids") List projectIds +) { + /** Copies lists and maps into unmodifiable collections. */ + public UpdateTeamMemberAssignmentDataProjectAccess { + projectIds = Copies.list(projectIds); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateTeamMemberAssignmentDataProjectAccess. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.scope = scope; + builder.projectIds = projectIds; + return builder; + } + + /** Builds a {@link UpdateTeamMemberAssignmentDataProjectAccess}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ProjectAccessScope scope; + private List projectIds; + + private Builder() { + } + + /** Sets {@code scope}. */ + public Builder scope(ProjectAccessScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Returns the {@link UpdateTeamMemberAssignmentDataProjectAccess}. */ + public UpdateTeamMemberAssignmentDataProjectAccess build() { + return new UpdateTeamMemberAssignmentDataProjectAccess(scope, projectIds); + } + } +} diff --git a/src/main/java/co/lettermint/types/UpdateWebhookData.java b/src/main/java/co/lettermint/types/UpdateWebhookData.java new file mode 100644 index 0000000..f1723fa --- /dev/null +++ b/src/main/java/co/lettermint/types/UpdateWebhookData.java @@ -0,0 +1,160 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param name Optional: null omits it. + * @param url Optional: null omits it. + * @param events Optional: null omits it. + * @param enabled Optional: null omits it. + * @param includeMachineEvents Optional: null omits it. + * @param deliveryModeFilter Optional: null omits it. + * @param scope Optional: null omits it. + * @param projectIds Optional: null omits it. + * @param routeIds Optional: null omits it. + * @param routeId Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + * @param basicAuth Write-only credentials. Omit to keep credentials. Null removes Basic Auth. Optional and nullable: leave it unset to omit it, or pass null to send JSON null. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record UpdateWebhookData( + @JsonProperty("name") String name, + @JsonProperty("url") String url, + @JsonProperty("events") List events, + @JsonProperty("enabled") Boolean enabled, + @JsonProperty("include_machine_events") Boolean includeMachineEvents, + @JsonProperty("delivery_mode_filter") WebhookDeliveryModeFilter deliveryModeFilter, + @JsonProperty("scope") WebhookScope scope, + @JsonProperty("project_ids") List projectIds, + @JsonProperty("route_ids") List routeIds, + @JsonProperty("route_id") OptionalNullable routeId, + @JsonProperty("basic_auth") OptionalNullable basicAuth +) { + /** Copies lists and maps into unmodifiable collections. */ + public UpdateWebhookData { + events = Copies.list(events); + projectIds = Copies.list(projectIds); + routeIds = Copies.list(routeIds); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this UpdateWebhookData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.name = name; + builder.url = url; + builder.events = events; + builder.enabled = enabled; + builder.includeMachineEvents = includeMachineEvents; + builder.deliveryModeFilter = deliveryModeFilter; + builder.scope = scope; + builder.projectIds = projectIds; + builder.routeIds = routeIds; + builder.routeId = routeId; + builder.basicAuth = basicAuth; + return builder; + } + + /** Builds a {@link UpdateWebhookData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String name; + private String url; + private List events; + private Boolean enabled; + private Boolean includeMachineEvents; + private WebhookDeliveryModeFilter deliveryModeFilter; + private WebhookScope scope; + private List projectIds; + private List routeIds; + private OptionalNullable routeId; + private OptionalNullable basicAuth; + + private Builder() { + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code url}. */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** Sets {@code events}. */ + public Builder events(List events) { + this.events = events; + return this; + } + + /** Sets {@code enabled}. */ + public Builder enabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + /** Sets {@code include_machine_events}. */ + public Builder includeMachineEvents(Boolean includeMachineEvents) { + this.includeMachineEvents = includeMachineEvents; + return this; + } + + /** Sets {@code delivery_mode_filter}. */ + public Builder deliveryModeFilter(WebhookDeliveryModeFilter deliveryModeFilter) { + this.deliveryModeFilter = deliveryModeFilter; + return this; + } + + /** Sets {@code scope}. */ + public Builder scope(WebhookScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Sets {@code route_ids}. */ + public Builder routeIds(List routeIds) { + this.routeIds = routeIds; + return this; + } + + /** Sets {@code route_id}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder routeId(String routeId) { + this.routeId = OptionalNullable.of(routeId); + return this; + } + + /** Sets {@code basic_auth}. {@code null} sends JSON null; leave it unset to omit the field. */ + public Builder basicAuth(WebhookBasicAuthData basicAuth) { + this.basicAuth = OptionalNullable.of(basicAuth); + return this; + } + + /** Returns the {@link UpdateWebhookData}. */ + public UpdateWebhookData build() { + return new UpdateWebhookData(name, url, events, enabled, includeMachineEvents, deliveryModeFilter, scope, projectIds, routeIds, routeId, basicAuth); + } + } +} diff --git a/src/main/java/co/lettermint/types/ValidationError.java b/src/main/java/co/lettermint/types/ValidationError.java new file mode 100644 index 0000000..fcf7a41 --- /dev/null +++ b/src/main/java/co/lettermint/types/ValidationError.java @@ -0,0 +1,69 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; +import java.util.Map; + +/** + * @param message Errors overview. Always present. + * @param errors A detailed description of each field that failed validation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record ValidationError( + @JsonProperty("message") String message, + @JsonProperty("errors") Map> errors +) { + /** Copies lists and maps into unmodifiable collections. */ + public ValidationError { + errors = Copies.map(errors); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this ValidationError. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.message = message; + builder.errors = errors; + return builder; + } + + /** Builds a {@link ValidationError}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String message; + private Map> errors; + + private Builder() { + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Sets {@code errors}. */ + public Builder errors(Map> errors) { + this.errors = errors; + return this; + } + + /** Returns the {@link ValidationError}. */ + public ValidationError build() { + return new ValidationError(message, errors); + } + } +} diff --git a/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java b/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java new file mode 100644 index 0000000..31707f1 --- /dev/null +++ b/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param code Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record VerifyReportForwardingRequest( + @JsonProperty("code") String code +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this VerifyReportForwardingRequest. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.code = code; + return builder; + } + + /** Builds a {@link VerifyReportForwardingRequest}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String code; + + private Builder() { + } + + /** Sets {@code code}. */ + public Builder code(String code) { + this.code = code; + return this; + } + + /** Returns the {@link VerifyReportForwardingRequest}. */ + public VerifyReportForwardingRequest build() { + return new VerifyReportForwardingRequest(code); + } + } +} diff --git a/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java b/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java new file mode 100644 index 0000000..5c34e3b --- /dev/null +++ b/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java @@ -0,0 +1,52 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param data Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record VerifyReportForwardingResponse( + @JsonProperty("data") ReportForwardingResource data +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this VerifyReportForwardingResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + return builder; + } + + /** Builds a {@link VerifyReportForwardingResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private ReportForwardingResource data; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(ReportForwardingResource data) { + this.data = data; + return this; + } + + /** Returns the {@link VerifyReportForwardingResponse}. */ + public VerifyReportForwardingResponse build() { + return new VerifyReportForwardingResponse(data); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookBasicAuthData.java b/src/main/java/co/lettermint/types/WebhookBasicAuthData.java new file mode 100644 index 0000000..917e9aa --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookBasicAuthData.java @@ -0,0 +1,69 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param username Required. + * @param password Required. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookBasicAuthData( + @JsonProperty("username") String username, + @JsonProperty("password") String password +) { + + /** Credentials (password) are shown as {@code [redacted]}. */ + @Override + public String toString() { + return "WebhookBasicAuthData[username=" + username + + ", password=" + (password == null ? "null" : "[redacted]") + "]"; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookBasicAuthData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.username = username; + builder.password = password; + return builder; + } + + /** Builds a {@link WebhookBasicAuthData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String username; + private String password; + + private Builder() { + } + + /** Sets {@code username}. */ + public Builder username(String username) { + this.username = username; + return this; + } + + /** Sets {@code password}. */ + public Builder password(String password) { + this.password = password; + return this; + } + + /** Returns the {@link WebhookBasicAuthData}. */ + public WebhookBasicAuthData build() { + return new WebhookBasicAuthData(username, password); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookData.java b/src/main/java/co/lettermint/types/WebhookData.java new file mode 100644 index 0000000..213cdb9 --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookData.java @@ -0,0 +1,212 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param scope Always present. + * @param projectIds Always present. + * @param routeIds Always present. + * @param routeId Use route_ids. Always present; may be null. + * @param name Always present. + * @param url Always present. + * @param hasBasicAuth Always present. + * @param events Always present. + * @param enabled Always present. + * @param includeMachineEvents Always present. + * @param deliveryModeFilter Always present. + * @param lastCalledAt Always present; may be null. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookData( + @JsonProperty("id") String id, + @JsonProperty("scope") WebhookScope scope, + @JsonProperty("project_ids") List projectIds, + @JsonProperty("route_ids") List routeIds, + @JsonProperty("route_id") String routeId, + @JsonProperty("name") String name, + @JsonProperty("url") String url, + @JsonProperty("has_basic_auth") Boolean hasBasicAuth, + @JsonProperty("events") List events, + @JsonProperty("enabled") Boolean enabled, + @JsonProperty("include_machine_events") Boolean includeMachineEvents, + @JsonProperty("delivery_mode_filter") WebhookDeliveryModeFilter deliveryModeFilter, + @JsonProperty("last_called_at") String lastCalledAt, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public WebhookData { + projectIds = Copies.list(projectIds); + routeIds = Copies.list(routeIds); + events = Copies.list(events); + } + + /** + * Use route_ids. + * + * @return {@code route_id} + * @deprecated Deprecated by the API. + */ + @Deprecated + public String routeId() { + return routeId; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.scope = scope; + builder.projectIds = projectIds; + builder.routeIds = routeIds; + builder.routeId = routeId; + builder.name = name; + builder.url = url; + builder.hasBasicAuth = hasBasicAuth; + builder.events = events; + builder.enabled = enabled; + builder.includeMachineEvents = includeMachineEvents; + builder.deliveryModeFilter = deliveryModeFilter; + builder.lastCalledAt = lastCalledAt; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link WebhookData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private WebhookScope scope; + private List projectIds; + private List routeIds; + private String routeId; + private String name; + private String url; + private Boolean hasBasicAuth; + private List events; + private Boolean enabled; + private Boolean includeMachineEvents; + private WebhookDeliveryModeFilter deliveryModeFilter; + private String lastCalledAt; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code scope}. */ + public Builder scope(WebhookScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Sets {@code route_ids}. */ + public Builder routeIds(List routeIds) { + this.routeIds = routeIds; + return this; + } + + /** Sets {@code route_id}. */ + @Deprecated + public Builder routeId(String routeId) { + this.routeId = routeId; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code url}. */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** Sets {@code has_basic_auth}. */ + public Builder hasBasicAuth(Boolean hasBasicAuth) { + this.hasBasicAuth = hasBasicAuth; + return this; + } + + /** Sets {@code events}. */ + public Builder events(List events) { + this.events = events; + return this; + } + + /** Sets {@code enabled}. */ + public Builder enabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + /** Sets {@code include_machine_events}. */ + public Builder includeMachineEvents(Boolean includeMachineEvents) { + this.includeMachineEvents = includeMachineEvents; + return this; + } + + /** Sets {@code delivery_mode_filter}. */ + public Builder deliveryModeFilter(WebhookDeliveryModeFilter deliveryModeFilter) { + this.deliveryModeFilter = deliveryModeFilter; + return this; + } + + /** Sets {@code last_called_at}. */ + public Builder lastCalledAt(String lastCalledAt) { + this.lastCalledAt = lastCalledAt; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link WebhookData}. */ + public WebhookData build() { + return new WebhookData(id, scope, projectIds, routeIds, routeId, name, url, hasBasicAuth, events, enabled, includeMachineEvents, deliveryModeFilter, lastCalledAt, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryData.java b/src/main/java/co/lettermint/types/WebhookDeliveryData.java new file mode 100644 index 0000000..537a405 --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookDeliveryData.java @@ -0,0 +1,237 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param webhookId Always present. + * @param eventType Always present. + * @param sourceScope Always present; may be null. + * @param sourceProjectId Always present; may be null. + * @param sourceRouteId Always present; may be null. + * @param status Always present. + * @param sandbox Always present. + * @param attemptNumber Always present. + * @param httpStatusCode Always present; may be null. + * @param durationMs Always present; may be null. + * @param payload Always present. + * @param responseBody Always present; may be null. + * @param responseHeaders Always present; may be null. + * @param errorMessage Always present; may be null. + * @param deliveredAt Always present; may be null. + * @param timestamp Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookDeliveryData( + @JsonProperty("id") String id, + @JsonProperty("webhook_id") String webhookId, + @JsonProperty("event_type") WebhookEvent eventType, + @JsonProperty("source_scope") String sourceScope, + @JsonProperty("source_project_id") String sourceProjectId, + @JsonProperty("source_route_id") String sourceRouteId, + @JsonProperty("status") WebhookDeliveryStatus status, + @JsonProperty("sandbox") Boolean sandbox, + @JsonProperty("attempt_number") Long attemptNumber, + @JsonProperty("http_status_code") Long httpStatusCode, + @JsonProperty("duration_ms") Long durationMs, + @JsonProperty("payload") List payload, + @JsonProperty("response_body") String responseBody, + @JsonProperty("response_headers") List responseHeaders, + @JsonProperty("error_message") String errorMessage, + @JsonProperty("delivered_at") String deliveredAt, + @JsonProperty("timestamp") String timestamp +) { + /** Copies lists and maps into unmodifiable collections. */ + public WebhookDeliveryData { + payload = Copies.list(payload); + responseHeaders = Copies.list(responseHeaders); + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookDeliveryData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.webhookId = webhookId; + builder.eventType = eventType; + builder.sourceScope = sourceScope; + builder.sourceProjectId = sourceProjectId; + builder.sourceRouteId = sourceRouteId; + builder.status = status; + builder.sandbox = sandbox; + builder.attemptNumber = attemptNumber; + builder.httpStatusCode = httpStatusCode; + builder.durationMs = durationMs; + builder.payload = payload; + builder.responseBody = responseBody; + builder.responseHeaders = responseHeaders; + builder.errorMessage = errorMessage; + builder.deliveredAt = deliveredAt; + builder.timestamp = timestamp; + return builder; + } + + /** Builds a {@link WebhookDeliveryData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String webhookId; + private WebhookEvent eventType; + private String sourceScope; + private String sourceProjectId; + private String sourceRouteId; + private WebhookDeliveryStatus status; + private Boolean sandbox; + private Long attemptNumber; + private Long httpStatusCode; + private Long durationMs; + private List payload; + private String responseBody; + private List responseHeaders; + private String errorMessage; + private String deliveredAt; + private String timestamp; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code webhook_id}. */ + public Builder webhookId(String webhookId) { + this.webhookId = webhookId; + return this; + } + + /** Sets {@code event_type}. */ + public Builder eventType(WebhookEvent eventType) { + this.eventType = eventType; + return this; + } + + /** Sets {@code source_scope}. */ + public Builder sourceScope(String sourceScope) { + this.sourceScope = sourceScope; + return this; + } + + /** Sets {@code source_project_id}. */ + public Builder sourceProjectId(String sourceProjectId) { + this.sourceProjectId = sourceProjectId; + return this; + } + + /** Sets {@code source_route_id}. */ + public Builder sourceRouteId(String sourceRouteId) { + this.sourceRouteId = sourceRouteId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(WebhookDeliveryStatus status) { + this.status = status; + return this; + } + + /** Sets {@code sandbox}. */ + public Builder sandbox(Boolean sandbox) { + this.sandbox = sandbox; + return this; + } + + /** Sets {@code attempt_number}. */ + public Builder attemptNumber(Long attemptNumber) { + this.attemptNumber = attemptNumber; + return this; + } + + /** Sets {@code attempt_number}. */ + public Builder attemptNumber(long attemptNumber) { + this.attemptNumber = attemptNumber; + return this; + } + + /** Sets {@code http_status_code}. */ + public Builder httpStatusCode(Long httpStatusCode) { + this.httpStatusCode = httpStatusCode; + return this; + } + + /** Sets {@code http_status_code}. */ + public Builder httpStatusCode(long httpStatusCode) { + this.httpStatusCode = httpStatusCode; + return this; + } + + /** Sets {@code duration_ms}. */ + public Builder durationMs(Long durationMs) { + this.durationMs = durationMs; + return this; + } + + /** Sets {@code duration_ms}. */ + public Builder durationMs(long durationMs) { + this.durationMs = durationMs; + return this; + } + + /** Sets {@code payload}. */ + public Builder payload(List payload) { + this.payload = payload; + return this; + } + + /** Sets {@code response_body}. */ + public Builder responseBody(String responseBody) { + this.responseBody = responseBody; + return this; + } + + /** Sets {@code response_headers}. */ + public Builder responseHeaders(List responseHeaders) { + this.responseHeaders = responseHeaders; + return this; + } + + /** Sets {@code error_message}. */ + public Builder errorMessage(String errorMessage) { + this.errorMessage = errorMessage; + return this; + } + + /** Sets {@code delivered_at}. */ + public Builder deliveredAt(String deliveredAt) { + this.deliveredAt = deliveredAt; + return this; + } + + /** Sets {@code timestamp}. */ + public Builder timestamp(String timestamp) { + this.timestamp = timestamp; + return this; + } + + /** Returns the {@link WebhookDeliveryData}. */ + public WebhookDeliveryData build() { + return new WebhookDeliveryData(id, webhookId, eventType, sourceScope, sourceProjectId, sourceRouteId, status, sandbox, attemptNumber, httpStatusCode, durationMs, payload, responseBody, responseHeaders, errorMessage, deliveredAt, timestamp); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryListData.java b/src/main/java/co/lettermint/types/WebhookDeliveryListData.java new file mode 100644 index 0000000..30a44f8 --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookDeliveryListData.java @@ -0,0 +1,190 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * @param id Always present. + * @param webhookId Always present. + * @param eventType Always present. + * @param sourceScope Always present; may be null. + * @param sourceProjectId Always present; may be null. + * @param sourceRouteId Always present; may be null. + * @param status Always present. + * @param sandbox Always present. + * @param attemptNumber Always present. + * @param httpStatusCode Always present; may be null. + * @param durationMs Always present; may be null. + * @param deliveredAt Always present; may be null. + * @param createdAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookDeliveryListData( + @JsonProperty("id") String id, + @JsonProperty("webhook_id") String webhookId, + @JsonProperty("event_type") WebhookEvent eventType, + @JsonProperty("source_scope") String sourceScope, + @JsonProperty("source_project_id") String sourceProjectId, + @JsonProperty("source_route_id") String sourceRouteId, + @JsonProperty("status") WebhookDeliveryStatus status, + @JsonProperty("sandbox") Boolean sandbox, + @JsonProperty("attempt_number") Long attemptNumber, + @JsonProperty("http_status_code") Long httpStatusCode, + @JsonProperty("duration_ms") Long durationMs, + @JsonProperty("delivered_at") String deliveredAt, + @JsonProperty("created_at") String createdAt +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookDeliveryListData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.webhookId = webhookId; + builder.eventType = eventType; + builder.sourceScope = sourceScope; + builder.sourceProjectId = sourceProjectId; + builder.sourceRouteId = sourceRouteId; + builder.status = status; + builder.sandbox = sandbox; + builder.attemptNumber = attemptNumber; + builder.httpStatusCode = httpStatusCode; + builder.durationMs = durationMs; + builder.deliveredAt = deliveredAt; + builder.createdAt = createdAt; + return builder; + } + + /** Builds a {@link WebhookDeliveryListData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private String webhookId; + private WebhookEvent eventType; + private String sourceScope; + private String sourceProjectId; + private String sourceRouteId; + private WebhookDeliveryStatus status; + private Boolean sandbox; + private Long attemptNumber; + private Long httpStatusCode; + private Long durationMs; + private String deliveredAt; + private String createdAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code webhook_id}. */ + public Builder webhookId(String webhookId) { + this.webhookId = webhookId; + return this; + } + + /** Sets {@code event_type}. */ + public Builder eventType(WebhookEvent eventType) { + this.eventType = eventType; + return this; + } + + /** Sets {@code source_scope}. */ + public Builder sourceScope(String sourceScope) { + this.sourceScope = sourceScope; + return this; + } + + /** Sets {@code source_project_id}. */ + public Builder sourceProjectId(String sourceProjectId) { + this.sourceProjectId = sourceProjectId; + return this; + } + + /** Sets {@code source_route_id}. */ + public Builder sourceRouteId(String sourceRouteId) { + this.sourceRouteId = sourceRouteId; + return this; + } + + /** Sets {@code status}. */ + public Builder status(WebhookDeliveryStatus status) { + this.status = status; + return this; + } + + /** Sets {@code sandbox}. */ + public Builder sandbox(Boolean sandbox) { + this.sandbox = sandbox; + return this; + } + + /** Sets {@code attempt_number}. */ + public Builder attemptNumber(Long attemptNumber) { + this.attemptNumber = attemptNumber; + return this; + } + + /** Sets {@code attempt_number}. */ + public Builder attemptNumber(long attemptNumber) { + this.attemptNumber = attemptNumber; + return this; + } + + /** Sets {@code http_status_code}. */ + public Builder httpStatusCode(Long httpStatusCode) { + this.httpStatusCode = httpStatusCode; + return this; + } + + /** Sets {@code http_status_code}. */ + public Builder httpStatusCode(long httpStatusCode) { + this.httpStatusCode = httpStatusCode; + return this; + } + + /** Sets {@code duration_ms}. */ + public Builder durationMs(Long durationMs) { + this.durationMs = durationMs; + return this; + } + + /** Sets {@code duration_ms}. */ + public Builder durationMs(long durationMs) { + this.durationMs = durationMs; + return this; + } + + /** Sets {@code delivered_at}. */ + public Builder deliveredAt(String deliveredAt) { + this.deliveredAt = deliveredAt; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Returns the {@link WebhookDeliveryListData}. */ + public WebhookDeliveryListData build() { + return new WebhookDeliveryListData(id, webhookId, eventType, sourceScope, sourceProjectId, sourceRouteId, status, sandbox, attemptNumber, httpStatusCode, durationMs, deliveredAt, createdAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java b/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java new file mode 100644 index 0000000..3499403 --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class WebhookDeliveryModeFilter { + /** {@code "live"} */ + public static final WebhookDeliveryModeFilter LIVE = new WebhookDeliveryModeFilter("live"); + + /** {@code "sandbox"} */ + public static final WebhookDeliveryModeFilter SANDBOX = new WebhookDeliveryModeFilter("sandbox"); + + /** {@code "both"} */ + public static final WebhookDeliveryModeFilter BOTH = new WebhookDeliveryModeFilter("both"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(LIVE.value, LIVE); + known.put(SANDBOX.value, SANDBOX); + known.put(BOTH.value, BOTH); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private WebhookDeliveryModeFilter(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static WebhookDeliveryModeFilter of(String value) { + Objects.requireNonNull(value, "value"); + WebhookDeliveryModeFilter known = KNOWN.get(value); + return known != null ? known : new WebhookDeliveryModeFilter(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof WebhookDeliveryModeFilter that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java b/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java new file mode 100644 index 0000000..7697c3a --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java @@ -0,0 +1,98 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class WebhookDeliveryStatus { + /** {@code "pending"} */ + public static final WebhookDeliveryStatus PENDING = new WebhookDeliveryStatus("pending"); + + /** {@code "success"} */ + public static final WebhookDeliveryStatus SUCCESS = new WebhookDeliveryStatus("success"); + + /** {@code "failed"} */ + public static final WebhookDeliveryStatus FAILED = new WebhookDeliveryStatus("failed"); + + /** {@code "client_error"} */ + public static final WebhookDeliveryStatus CLIENT_ERROR = new WebhookDeliveryStatus("client_error"); + + /** {@code "server_error"} */ + public static final WebhookDeliveryStatus SERVER_ERROR = new WebhookDeliveryStatus("server_error"); + + /** {@code "timeout"} */ + public static final WebhookDeliveryStatus TIMEOUT = new WebhookDeliveryStatus("timeout"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(PENDING.value, PENDING); + known.put(SUCCESS.value, SUCCESS); + known.put(FAILED.value, FAILED); + known.put(CLIENT_ERROR.value, CLIENT_ERROR); + known.put(SERVER_ERROR.value, SERVER_ERROR); + known.put(TIMEOUT.value, TIMEOUT); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private WebhookDeliveryStatus(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static WebhookDeliveryStatus of(String value) { + Objects.requireNonNull(value, "value"); + WebhookDeliveryStatus known = KNOWN.get(value); + return known != null ? known : new WebhookDeliveryStatus(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof WebhookDeliveryStatus that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/WebhookEvent.java b/src/main/java/co/lettermint/types/WebhookEvent.java new file mode 100644 index 0000000..132af04 --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookEvent.java @@ -0,0 +1,158 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class WebhookEvent { + /** {@code "message.created"} */ + public static final WebhookEvent MESSAGE_CREATED = new WebhookEvent("message.created"); + + /** {@code "message.sent"} */ + public static final WebhookEvent MESSAGE_SENT = new WebhookEvent("message.sent"); + + /** {@code "message.delivered"} */ + public static final WebhookEvent MESSAGE_DELIVERED = new WebhookEvent("message.delivered"); + + /** {@code "message.auto_replied"} */ + public static final WebhookEvent MESSAGE_AUTO_REPLIED = new WebhookEvent("message.auto_replied"); + + /** {@code "message.hard_bounced"} */ + public static final WebhookEvent MESSAGE_HARD_BOUNCED = new WebhookEvent("message.hard_bounced"); + + /** {@code "message.soft_bounced"} */ + public static final WebhookEvent MESSAGE_SOFT_BOUNCED = new WebhookEvent("message.soft_bounced"); + + /** {@code "message.spam_complaint"} */ + public static final WebhookEvent MESSAGE_SPAM_COMPLAINT = new WebhookEvent("message.spam_complaint"); + + /** {@code "message.failed"} */ + public static final WebhookEvent MESSAGE_FAILED = new WebhookEvent("message.failed"); + + /** {@code "message.suppressed"} */ + public static final WebhookEvent MESSAGE_SUPPRESSED = new WebhookEvent("message.suppressed"); + + /** {@code "message.unsubscribed"} */ + public static final WebhookEvent MESSAGE_UNSUBSCRIBED = new WebhookEvent("message.unsubscribed"); + + /** {@code "message.opened"} */ + public static final WebhookEvent MESSAGE_OPENED = new WebhookEvent("message.opened"); + + /** {@code "message.clicked"} */ + public static final WebhookEvent MESSAGE_CLICKED = new WebhookEvent("message.clicked"); + + /** {@code "message.inbound"} */ + public static final WebhookEvent MESSAGE_INBOUND = new WebhookEvent("message.inbound"); + + /** {@code "message.policy_rejected"} */ + public static final WebhookEvent MESSAGE_POLICY_REJECTED = new WebhookEvent("message.policy_rejected"); + + /** {@code "message.scheduled"} */ + public static final WebhookEvent MESSAGE_SCHEDULED = new WebhookEvent("message.scheduled"); + + /** {@code "message.rescheduled"} */ + public static final WebhookEvent MESSAGE_RESCHEDULED = new WebhookEvent("message.rescheduled"); + + /** {@code "message.canceled"} */ + public static final WebhookEvent MESSAGE_CANCELED = new WebhookEvent("message.canceled"); + + /** {@code "message.released"} */ + public static final WebhookEvent MESSAGE_RELEASED = new WebhookEvent("message.released"); + + /** {@code "suppression.added"} */ + public static final WebhookEvent SUPPRESSION_ADDED = new WebhookEvent("suppression.added"); + + /** {@code "suppression.removed"} */ + public static final WebhookEvent SUPPRESSION_REMOVED = new WebhookEvent("suppression.removed"); + + /** {@code "webhook.test"} */ + public static final WebhookEvent WEBHOOK_TEST = new WebhookEvent("webhook.test"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(MESSAGE_CREATED.value, MESSAGE_CREATED); + known.put(MESSAGE_SENT.value, MESSAGE_SENT); + known.put(MESSAGE_DELIVERED.value, MESSAGE_DELIVERED); + known.put(MESSAGE_AUTO_REPLIED.value, MESSAGE_AUTO_REPLIED); + known.put(MESSAGE_HARD_BOUNCED.value, MESSAGE_HARD_BOUNCED); + known.put(MESSAGE_SOFT_BOUNCED.value, MESSAGE_SOFT_BOUNCED); + known.put(MESSAGE_SPAM_COMPLAINT.value, MESSAGE_SPAM_COMPLAINT); + known.put(MESSAGE_FAILED.value, MESSAGE_FAILED); + known.put(MESSAGE_SUPPRESSED.value, MESSAGE_SUPPRESSED); + known.put(MESSAGE_UNSUBSCRIBED.value, MESSAGE_UNSUBSCRIBED); + known.put(MESSAGE_OPENED.value, MESSAGE_OPENED); + known.put(MESSAGE_CLICKED.value, MESSAGE_CLICKED); + known.put(MESSAGE_INBOUND.value, MESSAGE_INBOUND); + known.put(MESSAGE_POLICY_REJECTED.value, MESSAGE_POLICY_REJECTED); + known.put(MESSAGE_SCHEDULED.value, MESSAGE_SCHEDULED); + known.put(MESSAGE_RESCHEDULED.value, MESSAGE_RESCHEDULED); + known.put(MESSAGE_CANCELED.value, MESSAGE_CANCELED); + known.put(MESSAGE_RELEASED.value, MESSAGE_RELEASED); + known.put(SUPPRESSION_ADDED.value, SUPPRESSION_ADDED); + known.put(SUPPRESSION_REMOVED.value, SUPPRESSION_REMOVED); + known.put(WEBHOOK_TEST.value, WEBHOOK_TEST); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private WebhookEvent(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static WebhookEvent of(String value) { + Objects.requireNonNull(value, "value"); + WebhookEvent known = KNOWN.get(value); + return known != null ? known : new WebhookEvent(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof WebhookEvent that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/WebhookListData.java b/src/main/java/co/lettermint/types/WebhookListData.java new file mode 100644 index 0000000..9449cf5 --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookListData.java @@ -0,0 +1,202 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param scope Always present. + * @param projectIds Always present. + * @param routeIds Always present. + * @param routeId Use route_ids. Always present; may be null. + * @param name Always present. + * @param url Always present. + * @param hasBasicAuth Always present. + * @param events Always present. + * @param enabled Always present. + * @param deliveryModeFilter Always present. + * @param lastCalledAt Always present; may be null. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookListData( + @JsonProperty("id") String id, + @JsonProperty("scope") WebhookScope scope, + @JsonProperty("project_ids") List projectIds, + @JsonProperty("route_ids") List routeIds, + @JsonProperty("route_id") String routeId, + @JsonProperty("name") String name, + @JsonProperty("url") String url, + @JsonProperty("has_basic_auth") Boolean hasBasicAuth, + @JsonProperty("events") List events, + @JsonProperty("enabled") Boolean enabled, + @JsonProperty("delivery_mode_filter") WebhookDeliveryModeFilter deliveryModeFilter, + @JsonProperty("last_called_at") String lastCalledAt, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public WebhookListData { + projectIds = Copies.list(projectIds); + routeIds = Copies.list(routeIds); + events = Copies.list(events); + } + + /** + * Use route_ids. + * + * @return {@code route_id} + * @deprecated Deprecated by the API. + */ + @Deprecated + public String routeId() { + return routeId; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookListData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.scope = scope; + builder.projectIds = projectIds; + builder.routeIds = routeIds; + builder.routeId = routeId; + builder.name = name; + builder.url = url; + builder.hasBasicAuth = hasBasicAuth; + builder.events = events; + builder.enabled = enabled; + builder.deliveryModeFilter = deliveryModeFilter; + builder.lastCalledAt = lastCalledAt; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link WebhookListData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private WebhookScope scope; + private List projectIds; + private List routeIds; + private String routeId; + private String name; + private String url; + private Boolean hasBasicAuth; + private List events; + private Boolean enabled; + private WebhookDeliveryModeFilter deliveryModeFilter; + private String lastCalledAt; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code scope}. */ + public Builder scope(WebhookScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Sets {@code route_ids}. */ + public Builder routeIds(List routeIds) { + this.routeIds = routeIds; + return this; + } + + /** Sets {@code route_id}. */ + @Deprecated + public Builder routeId(String routeId) { + this.routeId = routeId; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code url}. */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** Sets {@code has_basic_auth}. */ + public Builder hasBasicAuth(Boolean hasBasicAuth) { + this.hasBasicAuth = hasBasicAuth; + return this; + } + + /** Sets {@code events}. */ + public Builder events(List events) { + this.events = events; + return this; + } + + /** Sets {@code enabled}. */ + public Builder enabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + /** Sets {@code delivery_mode_filter}. */ + public Builder deliveryModeFilter(WebhookDeliveryModeFilter deliveryModeFilter) { + this.deliveryModeFilter = deliveryModeFilter; + return this; + } + + /** Sets {@code last_called_at}. */ + public Builder lastCalledAt(String lastCalledAt) { + this.lastCalledAt = lastCalledAt; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link WebhookListData}. */ + public WebhookListData build() { + return new WebhookListData(id, scope, projectIds, routeIds, routeId, name, url, hasBasicAuth, events, enabled, deliveryModeFilter, lastCalledAt, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookMutationResponse.java b/src/main/java/co/lettermint/types/WebhookMutationResponse.java new file mode 100644 index 0000000..e110dce --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookMutationResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The webhook after a change, with a confirmation message. + * + * @param data Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookMutationResponse( + @JsonProperty("data") WebhookData data, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookMutationResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + return builder; + } + + /** Builds a {@link WebhookMutationResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private WebhookData data; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(WebhookData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link WebhookMutationResponse}. */ + public WebhookMutationResponse build() { + return new WebhookMutationResponse(data, message); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookScope.java b/src/main/java/co/lettermint/types/WebhookScope.java new file mode 100644 index 0000000..2767a8f --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookScope.java @@ -0,0 +1,86 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** An open enum: values that the API adds later decode as well and keep their raw value. */ +public final class WebhookScope { + /** {@code "team"} */ + public static final WebhookScope TEAM = new WebhookScope("team"); + + /** {@code "project"} */ + public static final WebhookScope PROJECT = new WebhookScope("project"); + + /** {@code "route"} */ + public static final WebhookScope ROUTE = new WebhookScope("route"); + + private static final Map KNOWN; + private static final List VALUES; + + static { + Map known = new LinkedHashMap<>(); + known.put(TEAM.value, TEAM); + known.put(PROJECT.value, PROJECT); + known.put(ROUTE.value, ROUTE); + KNOWN = Collections.unmodifiableMap(known); + VALUES = List.copyOf(known.values()); + } + + private final String value; + + private WebhookScope(String value) { + this.value = value; + } + + /** Returns the constant for a known value, or a new instance that keeps an unknown value. */ + @JsonCreator(mode = JsonCreator.Mode.DELEGATING) + public static WebhookScope of(String value) { + Objects.requireNonNull(value, "value"); + WebhookScope known = KNOWN.get(value); + return known != null ? known : new WebhookScope(value); + } + + /** The known values, in the order of the specification. */ + public static List values() { + return VALUES; + } + + /** The raw value, as sent by the API. */ + @JsonValue + public String value() { + return value; + } + + /** Whether this SDK version knows the value. */ + public boolean isKnown() { + return KNOWN.containsKey(value); + } + + @Override + public boolean equals(Object other) { + return other instanceof WebhookScope that && value.equals(that.value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + /** The raw value. */ + @Override + public String toString() { + return value; + } +} diff --git a/src/main/java/co/lettermint/types/WebhookSecretData.java b/src/main/java/co/lettermint/types/WebhookSecretData.java new file mode 100644 index 0000000..623253a --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookSecretData.java @@ -0,0 +1,243 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +/** + * @param id Always present. + * @param scope Always present. + * @param projectIds Always present. + * @param routeIds Always present. + * @param routeId Use route_ids. Always present; may be null. + * @param name Always present. + * @param url Always present. + * @param hasBasicAuth Always present. + * @param events Always present. + * @param enabled Always present. + * @param includeMachineEvents Always present. + * @param deliveryModeFilter Always present. + * @param secret Always present. + * @param lastCalledAt Always present; may be null. + * @param createdAt Always present. + * @param updatedAt Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookSecretData( + @JsonProperty("id") String id, + @JsonProperty("scope") WebhookScope scope, + @JsonProperty("project_ids") List projectIds, + @JsonProperty("route_ids") List routeIds, + @JsonProperty("route_id") String routeId, + @JsonProperty("name") String name, + @JsonProperty("url") String url, + @JsonProperty("has_basic_auth") Boolean hasBasicAuth, + @JsonProperty("events") List events, + @JsonProperty("enabled") Boolean enabled, + @JsonProperty("include_machine_events") Boolean includeMachineEvents, + @JsonProperty("delivery_mode_filter") WebhookDeliveryModeFilter deliveryModeFilter, + @JsonProperty("secret") String secret, + @JsonProperty("last_called_at") String lastCalledAt, + @JsonProperty("created_at") String createdAt, + @JsonProperty("updated_at") String updatedAt +) { + /** Copies lists and maps into unmodifiable collections. */ + public WebhookSecretData { + projectIds = Copies.list(projectIds); + routeIds = Copies.list(routeIds); + events = Copies.list(events); + } + + /** + * Use route_ids. + * + * @return {@code route_id} + * @deprecated Deprecated by the API. + */ + @Deprecated + public String routeId() { + return routeId; + } + + /** Credentials (secret) are shown as {@code [redacted]}. */ + @Override + public String toString() { + return "WebhookSecretData[id=" + id + + ", scope=" + scope + + ", projectIds=" + projectIds + + ", routeIds=" + routeIds + + ", routeId=" + routeId + + ", name=" + name + + ", url=" + url + + ", hasBasicAuth=" + hasBasicAuth + + ", events=" + events + + ", enabled=" + enabled + + ", includeMachineEvents=" + includeMachineEvents + + ", deliveryModeFilter=" + deliveryModeFilter + + ", secret=" + (secret == null ? "null" : "[redacted]") + + ", lastCalledAt=" + lastCalledAt + + ", createdAt=" + createdAt + + ", updatedAt=" + updatedAt + "]"; + } + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookSecretData. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.id = id; + builder.scope = scope; + builder.projectIds = projectIds; + builder.routeIds = routeIds; + builder.routeId = routeId; + builder.name = name; + builder.url = url; + builder.hasBasicAuth = hasBasicAuth; + builder.events = events; + builder.enabled = enabled; + builder.includeMachineEvents = includeMachineEvents; + builder.deliveryModeFilter = deliveryModeFilter; + builder.secret = secret; + builder.lastCalledAt = lastCalledAt; + builder.createdAt = createdAt; + builder.updatedAt = updatedAt; + return builder; + } + + /** Builds a {@link WebhookSecretData}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private String id; + private WebhookScope scope; + private List projectIds; + private List routeIds; + private String routeId; + private String name; + private String url; + private Boolean hasBasicAuth; + private List events; + private Boolean enabled; + private Boolean includeMachineEvents; + private WebhookDeliveryModeFilter deliveryModeFilter; + private String secret; + private String lastCalledAt; + private String createdAt; + private String updatedAt; + + private Builder() { + } + + /** Sets {@code id}. */ + public Builder id(String id) { + this.id = id; + return this; + } + + /** Sets {@code scope}. */ + public Builder scope(WebhookScope scope) { + this.scope = scope; + return this; + } + + /** Sets {@code project_ids}. */ + public Builder projectIds(List projectIds) { + this.projectIds = projectIds; + return this; + } + + /** Sets {@code route_ids}. */ + public Builder routeIds(List routeIds) { + this.routeIds = routeIds; + return this; + } + + /** Sets {@code route_id}. */ + @Deprecated + public Builder routeId(String routeId) { + this.routeId = routeId; + return this; + } + + /** Sets {@code name}. */ + public Builder name(String name) { + this.name = name; + return this; + } + + /** Sets {@code url}. */ + public Builder url(String url) { + this.url = url; + return this; + } + + /** Sets {@code has_basic_auth}. */ + public Builder hasBasicAuth(Boolean hasBasicAuth) { + this.hasBasicAuth = hasBasicAuth; + return this; + } + + /** Sets {@code events}. */ + public Builder events(List events) { + this.events = events; + return this; + } + + /** Sets {@code enabled}. */ + public Builder enabled(Boolean enabled) { + this.enabled = enabled; + return this; + } + + /** Sets {@code include_machine_events}. */ + public Builder includeMachineEvents(Boolean includeMachineEvents) { + this.includeMachineEvents = includeMachineEvents; + return this; + } + + /** Sets {@code delivery_mode_filter}. */ + public Builder deliveryModeFilter(WebhookDeliveryModeFilter deliveryModeFilter) { + this.deliveryModeFilter = deliveryModeFilter; + return this; + } + + /** Sets {@code secret}. */ + public Builder secret(String secret) { + this.secret = secret; + return this; + } + + /** Sets {@code last_called_at}. */ + public Builder lastCalledAt(String lastCalledAt) { + this.lastCalledAt = lastCalledAt; + return this; + } + + /** Sets {@code created_at}. */ + public Builder createdAt(String createdAt) { + this.createdAt = createdAt; + return this; + } + + /** Sets {@code updated_at}. */ + public Builder updatedAt(String updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + /** Returns the {@link WebhookSecretData}. */ + public WebhookSecretData build() { + return new WebhookSecretData(id, scope, projectIds, routeIds, routeId, name, url, hasBasicAuth, events, enabled, includeMachineEvents, deliveryModeFilter, secret, lastCalledAt, createdAt, updatedAt); + } + } +} diff --git a/src/main/java/co/lettermint/types/WebhookSecretResponse.java b/src/main/java/co/lettermint/types/WebhookSecretResponse.java new file mode 100644 index 0000000..b1162ad --- /dev/null +++ b/src/main/java/co/lettermint/types/WebhookSecretResponse.java @@ -0,0 +1,64 @@ +// Generated by lettermint/sdk-generator — do not edit. +// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f +// team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd +// Naming profile: next + +package co.lettermint.types; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +/** + * The webhook with its signing secret, which is only returned when the secret is created or regenerated. + * + * @param data Always present. + * @param message Human-readable confirmation. Always present. + */ +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public record WebhookSecretResponse( + @JsonProperty("data") WebhookSecretData data, + @JsonProperty("message") String message +) { + + /** Returns an empty builder. */ + public static Builder builder() { + return new Builder(); + } + + /** Returns a builder with the values of this WebhookSecretResponse. */ + public Builder toBuilder() { + Builder builder = new Builder(); + builder.data = data; + builder.message = message; + return builder; + } + + /** Builds a {@link WebhookSecretResponse}. Not thread-safe; the built value is immutable. */ + public static final class Builder { + private WebhookSecretData data; + private String message; + + private Builder() { + } + + /** Sets {@code data}. */ + public Builder data(WebhookSecretData data) { + this.data = data; + return this; + } + + /** Sets {@code message}. */ + public Builder message(String message) { + this.message = message; + return this; + } + + /** Returns the {@link WebhookSecretResponse}. */ + public WebhookSecretResponse build() { + return new WebhookSecretResponse(data, message); + } + } +} From b8d271b5aa22090a404b5e56cc245a72c021a0eb Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Sat, 3 Oct 2026 23:59:03 +0200 Subject: [PATCH 3/6] feat!: rewrite the SDK for 3.0 with stateless sending and per-surface tokens One thread-safe client replaces Lettermint.email(), Lettermint.api(), ApiClient and LettermintClient: Lettermint.builder().sendingToken(...) .teamToken(...).build(), or Lettermint.of(token) with prefix detection. emails() uses the sending token, every other part the team token, and ping, messages.reschedule and messages.cancel accept either. A missing token is a LettermintConfigException that names the option. Sending holds no state: emails().send(EmailMessage, SendOptions), sendBatch and an immutable compose() builder whose setters return new builders. The Idempotency-Key is a per-call option. Tags are validated before any request. The transport uses java.net.http with redirects never followed (a 3xx is a RedirectException), no retries, a timeout that covers the whole request, cancellation by thread interrupt, typed exceptions for every outcome and no tokens in toString or exception messages. OkHttp is removed. Lists return CursorPage and iterate() follows next_cursor. Webhook verification requires X-Lettermint-Signature and X-Lettermint-Delivery, accepts any matching v1, rejects a negative tolerance and reports a WebhookVerificationException.Reason. BREAKING CHANGE: every 2.x entry point, model and exception is replaced; Java 17 or later is required. See UPGRADE.md. --- build.gradle | 10 +- pom.xml | 147 ------ .../java/co/lettermint/CursorIterable.java | 82 +++ src/main/java/co/lettermint/Domains.java | 229 +++++++++ .../java/co/lettermint/EmailAttachment.java | 112 +++++ src/main/java/co/lettermint/EmailBuilder.java | 250 +++++++++ src/main/java/co/lettermint/EmailMessage.java | 475 ++++++++++++++++++ .../java/co/lettermint/EmailValidation.java | 58 +++ src/main/java/co/lettermint/Emails.java | 125 +++++ src/main/java/co/lettermint/Lettermint.java | 310 ++++++++++-- src/main/java/co/lettermint/Messages.java | 301 +++++++++++ src/main/java/co/lettermint/Projects.java | 220 ++++++++ src/main/java/co/lettermint/QueryString.java | 86 ++++ .../java/co/lettermint/ReportForwarding.java | 130 +++++ .../java/co/lettermint/RequestOptions.java | 25 + src/main/java/co/lettermint/Routes.java | 214 ++++++++ src/main/java/co/lettermint/Secret.java | 24 + src/main/java/co/lettermint/SendOptions.java | 51 ++ src/main/java/co/lettermint/Stats.java | 40 ++ src/main/java/co/lettermint/Suppressions.java | 125 +++++ src/main/java/co/lettermint/Team.java | 121 +++++ src/main/java/co/lettermint/TeamMembers.java | 125 +++++ src/main/java/co/lettermint/Tokens.java | 50 ++ src/main/java/co/lettermint/Transport.java | 443 ++++++++++++++++ src/main/java/co/lettermint/Webhook.java | 363 +++++++++++++ .../java/co/lettermint/WebhookDeliveries.java | 110 ++++ .../java/co/lettermint/WebhookPayload.java | 81 +++ src/main/java/co/lettermint/Webhooks.java | 224 +++++++++ .../java/co/lettermint/api/ApiClient.java | 409 --------------- .../lettermint/client/LettermintClient.java | 260 ---------- .../lettermint/endpoints/EmailEndpoint.java | 388 -------------- .../co/lettermint/endpoints/Endpoint.java | 15 - .../lettermint/exceptions/ApiException.java | 57 +++ .../exceptions/AuthenticationException.java | 17 + .../exceptions/ConflictException.java | 17 + .../exceptions/ConnectionException.java | 13 + .../exceptions/HttpRequestException.java | 30 -- .../exceptions/LettermintConfigException.java | 16 + .../exceptions/LettermintException.java | 12 +- .../LettermintValidationException.java | 27 + .../exceptions/NotFoundException.java | 17 + .../exceptions/PermissionException.java | 17 + .../exceptions/RateLimitException.java | 30 ++ .../exceptions/RedirectException.java | 26 + .../exceptions/ServerException.java | 17 + .../exceptions/TimeoutException.java | 31 ++ .../UnexpectedResponseException.java | 40 ++ .../exceptions/ValidationException.java | 32 +- .../WebhookVerificationException.java | 57 +++ .../webhook/InvalidSignatureException.java | 15 - .../webhook/TimestampToleranceException.java | 24 - .../webhook/WebhookVerificationException.java | 17 - .../java/co/lettermint/models/Attachment.java | 50 -- .../java/co/lettermint/models/MessageTag.java | 35 -- .../lettermint/models/SendEmailResponse.java | 73 --- .../models/api/AnalyticsRequest.java | 47 -- .../api/AnalyticsRequestFiltersItem.java | 17 - .../models/api/AnalyticsRequestSort.java | 13 - .../models/api/AnalyticsResponse.java | 16 - .../models/api/AnalyticsResponseData.java | 18 - .../models/api/AnalyticsResponseMeta.java | 55 -- .../api/AnalyticsResponseMetaComparison.java | 16 - .../api/AnalyticsResponsePagination.java | 19 - .../models/api/AnalyticsResponsePayload.java | 17 - ...AnalyticsResponsePayloadBreakdownItem.java | 27 - ...csResponsePayloadBreakdownItemMetrics.java | 208 -------- ...sResponsePayloadBreakdownItemPrevious.java | 13 - ...sePayloadBreakdownItemPreviousMetrics.java | 208 -------- ...PayloadBreakdownItemPreviousRateBases.java | 28 -- ...akdownItemPreviousRateBasesBounceRate.java | 13 - ...ownItemPreviousRateBasesComplaintRate.java | 13 - ...downItemPreviousRateBasesDeferralRate.java | 13 - ...downItemPreviousRateBasesDeliveryRate.java | 13 - ...reviousRateBasesEffectiveDeliveryRate.java | 13 - ...wnItemPreviousRateBasesHumanClickRate.java | 13 - ...ownItemPreviousRateBasesHumanOpenRate.java | 13 - ...ResponsePayloadBreakdownItemRateBases.java | 28 -- ...yloadBreakdownItemRateBasesBounceRate.java | 13 - ...adBreakdownItemRateBasesComplaintRate.java | 13 - ...oadBreakdownItemRateBasesDeferralRate.java | 13 - ...oadBreakdownItemRateBasesDeliveryRate.java | 13 - ...ownItemRateBasesEffectiveDeliveryRate.java | 13 - ...dBreakdownItemRateBasesHumanClickRate.java | 13 - ...adBreakdownItemRateBasesHumanOpenRate.java | 13 - ...ResponsePayloadBreakdownItemTrendItem.java | 32 -- ...ePayloadBreakdownItemTrendItemMetrics.java | 208 -------- ...PayloadBreakdownItemTrendItemPrevious.java | 13 - ...BreakdownItemTrendItemPreviousMetrics.java | 208 -------- ...eakdownItemTrendItemPreviousRateBases.java | 28 -- ...mTrendItemPreviousRateBasesBounceRate.java | 13 - ...endItemPreviousRateBasesComplaintRate.java | 13 - ...rendItemPreviousRateBasesDeferralRate.java | 13 - ...rendItemPreviousRateBasesDeliveryRate.java | 13 - ...reviousRateBasesEffectiveDeliveryRate.java | 13 - ...ndItemPreviousRateBasesHumanClickRate.java | 13 - ...endItemPreviousRateBasesHumanOpenRate.java | 13 - ...ayloadBreakdownItemTrendItemRateBases.java | 28 -- ...kdownItemTrendItemRateBasesBounceRate.java | 13 - ...wnItemTrendItemRateBasesComplaintRate.java | 13 - ...ownItemTrendItemRateBasesDeferralRate.java | 13 - ...ownItemTrendItemRateBasesDeliveryRate.java | 13 - ...endItemRateBasesEffectiveDeliveryRate.java | 13 - ...nItemTrendItemRateBasesHumanClickRate.java | 13 - ...wnItemTrendItemRateBasesHumanOpenRate.java | 13 - .../api/AnalyticsResponsePayloadSummary.java | 20 - ...nalyticsResponsePayloadSummaryMetrics.java | 208 -------- ...alyticsResponsePayloadSummaryPrevious.java | 13 - ...ResponsePayloadSummaryPreviousMetrics.java | 208 -------- ...sponsePayloadSummaryPreviousRateBases.java | 28 -- ...oadSummaryPreviousRateBasesBounceRate.java | 13 - ...SummaryPreviousRateBasesComplaintRate.java | 13 - ...dSummaryPreviousRateBasesDeferralRate.java | 13 - ...dSummaryPreviousRateBasesDeliveryRate.java | 13 - ...reviousRateBasesEffectiveDeliveryRate.java | 13 - ...ummaryPreviousRateBasesHumanClickRate.java | 13 - ...SummaryPreviousRateBasesHumanOpenRate.java | 13 - ...lyticsResponsePayloadSummaryRateBases.java | 28 -- ...onsePayloadSummaryRateBasesBounceRate.java | 13 - ...ePayloadSummaryRateBasesComplaintRate.java | 13 - ...sePayloadSummaryRateBasesDeferralRate.java | 13 - ...sePayloadSummaryRateBasesDeliveryRate.java | 13 - ...SummaryRateBasesEffectiveDeliveryRate.java | 13 - ...PayloadSummaryRateBasesHumanClickRate.java | 13 - ...ePayloadSummaryRateBasesHumanOpenRate.java | 13 - ...nalyticsResponsePayloadTimeSeriesItem.java | 32 -- ...sResponsePayloadTimeSeriesItemMetrics.java | 208 -------- ...ResponsePayloadTimeSeriesItemPrevious.java | 13 - ...ePayloadTimeSeriesItemPreviousMetrics.java | 208 -------- ...ayloadTimeSeriesItemPreviousRateBases.java | 28 -- ...SeriesItemPreviousRateBasesBounceRate.java | 13 - ...iesItemPreviousRateBasesComplaintRate.java | 13 - ...riesItemPreviousRateBasesDeferralRate.java | 13 - ...riesItemPreviousRateBasesDeliveryRate.java | 13 - ...reviousRateBasesEffectiveDeliveryRate.java | 13 - ...esItemPreviousRateBasesHumanClickRate.java | 13 - ...iesItemPreviousRateBasesHumanOpenRate.java | 13 - ...esponsePayloadTimeSeriesItemRateBases.java | 28 -- ...loadTimeSeriesItemRateBasesBounceRate.java | 13 - ...dTimeSeriesItemRateBasesComplaintRate.java | 13 - ...adTimeSeriesItemRateBasesDeferralRate.java | 13 - ...adTimeSeriesItemRateBasesDeliveryRate.java | 13 - ...iesItemRateBasesEffectiveDeliveryRate.java | 13 - ...TimeSeriesItemRateBasesHumanClickRate.java | 13 - ...dTimeSeriesItemRateBasesHumanOpenRate.java | 13 - .../models/api/AttachmentDelivery.java | 8 - .../models/api/BlockedFileTypesResponse.java | 14 - .../models/api/BuiltInTeamRole.java | 9 - .../api/CancelScheduledMessageResponse.java | 7 - .../models/api/CursorPaginator.java | 29 -- .../lettermint/models/api/DeliveryMode.java | 8 - .../co/lettermint/models/api/DkimMode.java | 8 - .../models/api/DnsRecordPurpose.java | 11 - .../models/api/DnsRecordStatus.java | 9 - .../models/api/DnsVerificationScope.java | 10 - .../co/lettermint/models/api/DomainData.java | 33 -- .../models/api/DomainDestroyResponse.java | 10 - .../models/api/DomainDnsRecordData.java | 40 -- .../models/api/DomainIndexResponse.java | 29 -- .../lettermint/models/api/DomainListData.java | 25 - .../lettermint/models/api/DomainStatus.java | 10 - .../api/DomainUpdateProjectsResponse.java | 13 - .../api/DomainVerifyDnsRecordsResponse.java | 15 - ...DomainVerifySpecificDnsRecordResponse.java | 10 - .../api/GetReportForwardingResponse.java | 10 - .../lettermint/models/api/InitialRoutes.java | 9 - .../models/api/MessageAttachmentData.java | 19 - .../co/lettermint/models/api/MessageData.java | 75 --- .../models/api/MessageEventData.java | 27 - .../models/api/MessageEventType.java | 30 -- .../models/api/MessageEventsResponse.java | 18 - .../models/api/MessageIndexResponse.java | 18 - .../models/api/MessageListData.java | 63 --- .../models/api/MessageRecipientData.java | 16 - .../models/api/MessageStatsData.java | 19 - .../lettermint/models/api/MessageStatus.java | 23 - .../co/lettermint/models/api/MessageType.java | 8 - .../models/api/OptionalNullable.java | 57 --- .../java/co/lettermint/models/api/Plan.java | 10 - .../api/ProcessInboundMessageResponse.java | 11 - .../models/api/ProjectAccessScope.java | 8 - .../models/api/ProjectCreatedData.java | 16 - .../co/lettermint/models/api/ProjectData.java | 56 --- .../models/api/ProjectDestroyResponse.java | 10 - .../models/api/ProjectIndexResponse.java | 29 -- .../models/api/ProjectListData.java | 34 -- .../api/ProjectRotateTokenResponse.java | 16 - .../models/api/ProjectStoreResponse.java | 16 - .../models/api/ProjectUpdateResponse.java | 13 - .../models/api/RbacConflictCode.java | 11 - .../lettermint/models/api/RbacPermission.java | 47 -- .../co/lettermint/models/api/RecordType.java | 9 - .../models/api/ReportForwardingRequest.java | 10 - .../models/api/ReportForwardingResource.java | 16 - .../models/api/RescheduleMessageRequest.java | 10 - .../models/api/RescheduleMessageResponse.java | 16 - .../ResendReportForwardingCodeResponse.java | 10 - .../co/lettermint/models/api/RouteData.java | 69 --- .../models/api/RouteDestroyResponse.java | 10 - .../models/api/RouteIndexResponse.java | 29 -- .../lettermint/models/api/RouteListData.java | 34 -- .../models/api/RouteStatisticData.java | 49 -- .../models/api/RouteStoreResponse.java | 13 - .../co/lettermint/models/api/RouteType.java | 9 - .../models/api/RouteUpdateResponse.java | 13 - .../api/RouteVerifyInboundDomainResponse.java | 11 - .../lettermint/models/api/SandboxResult.java | 17 - .../models/api/SendMailRequest.java | 60 --- .../models/api/SendMailResponse.java | 22 - .../co/lettermint/models/api/SpamSymbol.java | 20 - .../lettermint/models/api/StatsDailyData.java | 55 -- .../co/lettermint/models/api/StatsData.java | 20 - .../models/api/StatsInboundData.java | 10 - .../models/api/StatsRequestData.java | 19 - .../models/api/StatsTotalsData.java | 52 -- .../lettermint/models/api/StatsTypeData.java | 16 - .../models/api/StoreDomainData.java | 10 - .../models/api/StoreProjectData.java | 25 - .../lettermint/models/api/StoreRouteData.java | 31 -- .../models/api/StoreSuppressionData.java | 29 -- .../models/api/StoreWebhookData.java | 42 -- .../models/api/SuppressedRecipientData.java | 37 -- .../models/api/SuppressionAppliesTo.java | 8 - .../api/SuppressionDestroyResponse.java | 22 - .../models/api/SuppressionIndexResponse.java | 29 -- .../models/api/SuppressionReason.java | 10 - .../models/api/SuppressionScope.java | 9 - .../api/SuppressionSourceMessageData.java | 19 - .../models/api/SuppressionStoreResponse.java | 14 - .../models/api/SuppressionType.java | 9 - .../lettermint/models/api/TeamAddonData.java | 13 - .../co/lettermint/models/api/TeamData.java | 47 -- .../lettermint/models/api/TeamMemberData.java | 26 - .../api/TeamMemberProjectAccessData.java | 15 - .../models/api/TeamMembersResponse.java | 29 -- .../lettermint/models/api/TeamRoleData.java | 23 - .../models/api/TeamRolesResponse.java | 11 - .../co/lettermint/models/api/TeamType.java | 8 - .../models/api/TeamUpdateResponse.java | 13 - .../models/api/TeamUsageDetailData.java | 14 - .../models/api/TeamUsagePeriodData.java | 19 - .../co/lettermint/models/api/TlsPolicy.java | 8 - .../models/api/UpdateDomainProjectsData.java | 11 - .../models/api/UpdateProjectData.java | 22 - .../api/UpdateReportForwardingRequest.java | 10 - .../api/UpdateReportForwardingResponse.java | 10 - .../models/api/UpdateRouteData.java | 25 - .../api/UpdateRouteInboundSettingsData.java | 16 - .../models/api/UpdateRouteSettingsData.java | 31 -- .../lettermint/models/api/UpdateTeamData.java | 10 - .../api/UpdateTeamMemberAssignmentData.java | 14 - .../models/api/UpdateWebhookData.java | 42 -- .../api/VerifyReportForwardingRequest.java | 10 - .../api/VerifyReportForwardingResponse.java | 10 - .../models/api/WebhookBasicAuthData.java | 13 - .../co/lettermint/models/api/WebhookData.java | 53 -- .../models/api/WebhookDeliveriesResponse.java | 29 -- .../models/api/WebhookDeliveryData.java | 59 --- .../models/api/WebhookDeliveryListData.java | 46 -- .../models/api/WebhookDeliveryModeFilter.java | 9 - .../models/api/WebhookDeliveryStatus.java | 12 - .../models/api/WebhookDestroyResponse.java | 10 - .../lettermint/models/api/WebhookEvent.java | 27 - .../models/api/WebhookIndexResponse.java | 29 -- .../models/api/WebhookListData.java | 50 -- .../api/WebhookRegenerateSecretResponse.java | 13 - .../lettermint/models/api/WebhookScope.java | 9 - .../models/api/WebhookSecretData.java | 56 --- .../models/api/WebhookStoreResponse.java | 13 - .../models/api/WebhookTestResponse.java | 13 - .../models/api/WebhookUpdateResponse.java | 13 - .../java/co/lettermint/webhooks/Webhook.java | 208 -------- .../lettermint/AnalyticsForwardingTest.java | 61 --- .../java/co/lettermint/ApiClientTest.java | 356 ------------- .../CancelBinaryCompatibilityTest.java | 87 ---- src/test/java/co/lettermint/ClientTest.java | 174 +++++++ .../java/co/lettermint/EmailEndpointTest.java | 303 ----------- src/test/java/co/lettermint/EmailsTest.java | 255 ++++++++++ src/test/java/co/lettermint/FakeServer.java | 158 ++++++ .../java/co/lettermint/LettermintTest.java | 39 -- .../lettermint/OkHttpCompatibilityTest.java | 99 ---- src/test/java/co/lettermint/TeamApiTest.java | 265 ++++++++++ .../java/co/lettermint/TransportTest.java | 295 +++++++++++ .../co/lettermint/WebhookBasicAuthTest.java | 59 --- src/test/java/co/lettermint/WebhookTest.java | 357 ++++++------- src/test/resources/webhooks.json | 444 ++++++++++++++++ 285 files changed, 6510 insertions(+), 8671 deletions(-) delete mode 100644 pom.xml create mode 100644 src/main/java/co/lettermint/CursorIterable.java create mode 100644 src/main/java/co/lettermint/Domains.java create mode 100644 src/main/java/co/lettermint/EmailAttachment.java create mode 100644 src/main/java/co/lettermint/EmailBuilder.java create mode 100644 src/main/java/co/lettermint/EmailMessage.java create mode 100644 src/main/java/co/lettermint/EmailValidation.java create mode 100644 src/main/java/co/lettermint/Emails.java create mode 100644 src/main/java/co/lettermint/Messages.java create mode 100644 src/main/java/co/lettermint/Projects.java create mode 100644 src/main/java/co/lettermint/QueryString.java create mode 100644 src/main/java/co/lettermint/ReportForwarding.java create mode 100644 src/main/java/co/lettermint/RequestOptions.java create mode 100644 src/main/java/co/lettermint/Routes.java create mode 100644 src/main/java/co/lettermint/Secret.java create mode 100644 src/main/java/co/lettermint/SendOptions.java create mode 100644 src/main/java/co/lettermint/Stats.java create mode 100644 src/main/java/co/lettermint/Suppressions.java create mode 100644 src/main/java/co/lettermint/Team.java create mode 100644 src/main/java/co/lettermint/TeamMembers.java create mode 100644 src/main/java/co/lettermint/Tokens.java create mode 100644 src/main/java/co/lettermint/Transport.java create mode 100644 src/main/java/co/lettermint/Webhook.java create mode 100644 src/main/java/co/lettermint/WebhookDeliveries.java create mode 100644 src/main/java/co/lettermint/WebhookPayload.java create mode 100644 src/main/java/co/lettermint/Webhooks.java delete mode 100644 src/main/java/co/lettermint/api/ApiClient.java delete mode 100644 src/main/java/co/lettermint/client/LettermintClient.java delete mode 100644 src/main/java/co/lettermint/endpoints/EmailEndpoint.java delete mode 100644 src/main/java/co/lettermint/endpoints/Endpoint.java create mode 100644 src/main/java/co/lettermint/exceptions/ApiException.java create mode 100644 src/main/java/co/lettermint/exceptions/AuthenticationException.java create mode 100644 src/main/java/co/lettermint/exceptions/ConflictException.java create mode 100644 src/main/java/co/lettermint/exceptions/ConnectionException.java delete mode 100644 src/main/java/co/lettermint/exceptions/HttpRequestException.java create mode 100644 src/main/java/co/lettermint/exceptions/LettermintConfigException.java create mode 100644 src/main/java/co/lettermint/exceptions/LettermintValidationException.java create mode 100644 src/main/java/co/lettermint/exceptions/NotFoundException.java create mode 100644 src/main/java/co/lettermint/exceptions/PermissionException.java create mode 100644 src/main/java/co/lettermint/exceptions/RateLimitException.java create mode 100644 src/main/java/co/lettermint/exceptions/RedirectException.java create mode 100644 src/main/java/co/lettermint/exceptions/ServerException.java create mode 100644 src/main/java/co/lettermint/exceptions/TimeoutException.java create mode 100644 src/main/java/co/lettermint/exceptions/UnexpectedResponseException.java create mode 100644 src/main/java/co/lettermint/exceptions/WebhookVerificationException.java delete mode 100644 src/main/java/co/lettermint/exceptions/webhook/InvalidSignatureException.java delete mode 100644 src/main/java/co/lettermint/exceptions/webhook/TimestampToleranceException.java delete mode 100644 src/main/java/co/lettermint/exceptions/webhook/WebhookVerificationException.java delete mode 100644 src/main/java/co/lettermint/models/Attachment.java delete mode 100644 src/main/java/co/lettermint/models/MessageTag.java delete mode 100644 src/main/java/co/lettermint/models/SendEmailResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsRequest.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsRequestFiltersItem.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsRequestSort.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponseData.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponseMeta.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponseMetaComparison.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePagination.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayload.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItem.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPrevious.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItem.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPrevious.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummary.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPrevious.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItem.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPrevious.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousMetrics.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBases.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesBounceRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesComplaintRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeferralRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesEffectiveDeliveryRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanClickRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanOpenRate.java delete mode 100644 src/main/java/co/lettermint/models/api/AttachmentDelivery.java delete mode 100644 src/main/java/co/lettermint/models/api/BlockedFileTypesResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/BuiltInTeamRole.java delete mode 100644 src/main/java/co/lettermint/models/api/CancelScheduledMessageResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/CursorPaginator.java delete mode 100644 src/main/java/co/lettermint/models/api/DeliveryMode.java delete mode 100644 src/main/java/co/lettermint/models/api/DkimMode.java delete mode 100644 src/main/java/co/lettermint/models/api/DnsRecordPurpose.java delete mode 100644 src/main/java/co/lettermint/models/api/DnsRecordStatus.java delete mode 100644 src/main/java/co/lettermint/models/api/DnsVerificationScope.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainData.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainDestroyResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainDnsRecordData.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainIndexResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainListData.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainStatus.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainUpdateProjectsResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainVerifyDnsRecordsResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/DomainVerifySpecificDnsRecordResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/GetReportForwardingResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/InitialRoutes.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageAttachmentData.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageData.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageEventData.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageEventType.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageEventsResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageIndexResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageListData.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageRecipientData.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageStatsData.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageStatus.java delete mode 100644 src/main/java/co/lettermint/models/api/MessageType.java delete mode 100644 src/main/java/co/lettermint/models/api/OptionalNullable.java delete mode 100644 src/main/java/co/lettermint/models/api/Plan.java delete mode 100644 src/main/java/co/lettermint/models/api/ProcessInboundMessageResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectAccessScope.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectCreatedData.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectData.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectDestroyResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectIndexResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectListData.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectRotateTokenResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectStoreResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/ProjectUpdateResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/RbacConflictCode.java delete mode 100644 src/main/java/co/lettermint/models/api/RbacPermission.java delete mode 100644 src/main/java/co/lettermint/models/api/RecordType.java delete mode 100644 src/main/java/co/lettermint/models/api/ReportForwardingRequest.java delete mode 100644 src/main/java/co/lettermint/models/api/ReportForwardingResource.java delete mode 100644 src/main/java/co/lettermint/models/api/RescheduleMessageRequest.java delete mode 100644 src/main/java/co/lettermint/models/api/RescheduleMessageResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/ResendReportForwardingCodeResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteData.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteDestroyResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteIndexResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteListData.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteStatisticData.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteStoreResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteType.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteUpdateResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/RouteVerifyInboundDomainResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/SandboxResult.java delete mode 100644 src/main/java/co/lettermint/models/api/SendMailRequest.java delete mode 100644 src/main/java/co/lettermint/models/api/SendMailResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/SpamSymbol.java delete mode 100644 src/main/java/co/lettermint/models/api/StatsDailyData.java delete mode 100644 src/main/java/co/lettermint/models/api/StatsData.java delete mode 100644 src/main/java/co/lettermint/models/api/StatsInboundData.java delete mode 100644 src/main/java/co/lettermint/models/api/StatsRequestData.java delete mode 100644 src/main/java/co/lettermint/models/api/StatsTotalsData.java delete mode 100644 src/main/java/co/lettermint/models/api/StatsTypeData.java delete mode 100644 src/main/java/co/lettermint/models/api/StoreDomainData.java delete mode 100644 src/main/java/co/lettermint/models/api/StoreProjectData.java delete mode 100644 src/main/java/co/lettermint/models/api/StoreRouteData.java delete mode 100644 src/main/java/co/lettermint/models/api/StoreSuppressionData.java delete mode 100644 src/main/java/co/lettermint/models/api/StoreWebhookData.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressedRecipientData.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionAppliesTo.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionDestroyResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionIndexResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionReason.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionScope.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionSourceMessageData.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionStoreResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/SuppressionType.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamAddonData.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamData.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamMemberData.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamMemberProjectAccessData.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamMembersResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamRoleData.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamRolesResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamType.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamUpdateResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamUsageDetailData.java delete mode 100644 src/main/java/co/lettermint/models/api/TeamUsagePeriodData.java delete mode 100644 src/main/java/co/lettermint/models/api/TlsPolicy.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateDomainProjectsData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateProjectData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateReportForwardingRequest.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateReportForwardingResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateRouteData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateRouteInboundSettingsData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateRouteSettingsData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateTeamData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateTeamMemberAssignmentData.java delete mode 100644 src/main/java/co/lettermint/models/api/UpdateWebhookData.java delete mode 100644 src/main/java/co/lettermint/models/api/VerifyReportForwardingRequest.java delete mode 100644 src/main/java/co/lettermint/models/api/VerifyReportForwardingResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookBasicAuthData.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookData.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookDeliveriesResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookDeliveryData.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookDeliveryListData.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookDeliveryModeFilter.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookDeliveryStatus.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookDestroyResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookEvent.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookIndexResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookListData.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookRegenerateSecretResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookScope.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookSecretData.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookStoreResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookTestResponse.java delete mode 100644 src/main/java/co/lettermint/models/api/WebhookUpdateResponse.java delete mode 100644 src/main/java/co/lettermint/webhooks/Webhook.java delete mode 100644 src/test/java/co/lettermint/AnalyticsForwardingTest.java delete mode 100644 src/test/java/co/lettermint/ApiClientTest.java delete mode 100644 src/test/java/co/lettermint/CancelBinaryCompatibilityTest.java create mode 100644 src/test/java/co/lettermint/ClientTest.java delete mode 100644 src/test/java/co/lettermint/EmailEndpointTest.java create mode 100644 src/test/java/co/lettermint/EmailsTest.java create mode 100644 src/test/java/co/lettermint/FakeServer.java delete mode 100644 src/test/java/co/lettermint/LettermintTest.java delete mode 100644 src/test/java/co/lettermint/OkHttpCompatibilityTest.java create mode 100644 src/test/java/co/lettermint/TeamApiTest.java create mode 100644 src/test/java/co/lettermint/TransportTest.java delete mode 100644 src/test/java/co/lettermint/WebhookBasicAuthTest.java create mode 100644 src/test/resources/webhooks.json diff --git a/build.gradle b/build.gradle index d0b1add..ccdbf49 100644 --- a/build.gradle +++ b/build.gradle @@ -22,10 +22,8 @@ repositories { dependencies { // Generated types use Jackson annotations and TypeReference in their public API. api 'com.fasterxml.jackson.core:jackson-databind:2.22.3' - implementation 'com.squareup.okhttp3:okhttp:4.12.0' testImplementation 'org.junit.jupiter:junit-jupiter:5.10.1' - testImplementation 'com.squareup.okhttp3:mockwebserver:4.12.0' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } @@ -34,6 +32,10 @@ tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' } +tasks.named('compileJava', JavaCompile) { + options.compilerArgs += ['-Xlint:all,-serial', '-Werror'] +} + tasks.named('test', Test) { useJUnitPlatform() testLogging { @@ -61,9 +63,9 @@ def generateBuildInfo = tasks.register('generateBuildInfo') { file.text = """package co.lettermint; /** Build information, generated by Gradle. */ -public final class BuildInfo { +final class BuildInfo { /** The SDK version. */ - public static final String VERSION = "${sdkVersion}"; + static final String VERSION = "${sdkVersion}"; private BuildInfo() { } diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 0e006c9..0000000 --- a/pom.xml +++ /dev/null @@ -1,147 +0,0 @@ - - - 4.0.0 - - co.lettermint - lettermint - 2.0.0 - jar - - Lettermint Java SDK - Official Java SDK for the Lettermint API - https://github.com/lettermint/lettermint-java - - - - MIT License - https://opensource.org/licenses/MIT - - - - - - Lettermint - support@lettermint.co - Lettermint B.V. - https://lettermint.co - - - - - scm:git:git://github.com/lettermint/lettermint-java.git - scm:git:ssh://github.com:lettermint/lettermint-java.git - https://github.com/lettermint/lettermint-java/tree/main - - - - 1.8 - 1.8 - UTF-8 - 4.12.0 - 2.22.2 - 5.10.1 - - - - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - - - org.junit.jupiter - junit-jupiter - ${junit.version} - test - - - com.squareup.okhttp3 - mockwebserver - ${okhttp.version} - test - - - - - - - - org.codehaus.mojo - templating-maven-plugin - 2.0.0 - - - filter-src - - filter-sources - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.0.0 - - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.0.0 - - - org.apache.maven.plugins - maven-jar-plugin - 2.0.0 - - - - true - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.0.0 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.0.0 - - - attach-javadocs - - jar - - - - - - - diff --git a/src/main/java/co/lettermint/CursorIterable.java b/src/main/java/co/lettermint/CursorIterable.java new file mode 100644 index 0000000..f76c85f --- /dev/null +++ b/src/main/java/co/lettermint/CursorIterable.java @@ -0,0 +1,82 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.Function; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +/** + * Every item of a cursor-paginated list, returned by the {@code iterate()} methods. + * + *

{@code
+ * for (DomainListData domain : lettermint.domains().iterate()) { ... }
+ * lettermint.messages().iterate(query).stream().limit(100).forEach(...);
+ * }
+ * + *

Pages are requested lazily, when iteration gets to them, by following {@code next_cursor} until it + * is null or empty, or repeats. Each {@link #iterator()} starts again from the first page. Errors are + * thrown from {@code hasNext()} and {@code next()}. + * + * @param the item type + */ +public final class CursorIterable implements Iterable { + private final Function> fetch; + + CursorIterable(Function> fetch) { + this.fetch = fetch; + } + + @Override + public Iterator iterator() { + return new Iterator<>() { + private Iterator items = Collections.emptyIterator(); + private final Set seen = new HashSet<>(); + private String cursor; + private boolean started; + private boolean done; + + @Override + public boolean hasNext() { + while (!items.hasNext() && !done) { + CursorPage page = fetch.apply(started ? cursor : null); + started = true; + items = page.data().iterator(); + String next = page.nextCursor(); + if (next == null || next.isEmpty() || !seen.add(next)) { + done = true; + } else { + cursor = next; + } + } + return items.hasNext(); + } + + @Override + public T next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + return items.next(); + } + }; + } + + /** + * @return a sequential stream over every item; pages are requested as the stream consumes them + */ + public Stream stream() { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator(), Spliterator.ORDERED), false); + } + + @Override + public String toString() { + return "CursorIterable"; + } +} diff --git a/src/main/java/co/lettermint/Domains.java b/src/main/java/co/lettermint/Domains.java new file mode 100644 index 0000000..d30b4d7 --- /dev/null +++ b/src/main/java/co/lettermint/Domains.java @@ -0,0 +1,229 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.DnsVerificationSuccessResponse; +import co.lettermint.types.DomainData; +import co.lettermint.types.DomainListData; +import co.lettermint.types.DomainMutationResponse; +import co.lettermint.types.GetDomainQuery; +import co.lettermint.types.ListDomainsQuery; +import co.lettermint.types.MessageResponse; +import co.lettermint.types.Operations; +import co.lettermint.types.StoreDomainData; +import co.lettermint.types.UpdateDomainProjectsData; + +/** Sending domains. Needs the team token. Thread-safe. */ +public final class Domains { + private final Transport transport; + + Domains(Transport transport) { + this.transport = transport; + } + + /** + * Lists domains, one page at a time. + * + * @return the response + */ + public CursorPage list() { + return list(null, null); + } + + /** + * Lists domains, one page at a time. + * + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(ListDomainsQuery query) { + return list(query, null); + } + + /** + * Lists domains, one page at a time. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(ListDomainsQuery query, RequestOptions options) { + return transport.call(Operations.LIST_DOMAINS, Transport.call("domains.list").query(query).options(options)); + } + + /** + * Iterates over every domain, following {@code next_cursor}. + * + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate() { + return iterate(null, null); + } + + /** + * Iterates over every domain, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListDomainsQuery query) { + return iterate(query, null); + } + + /** + * Iterates over every domain, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListDomainsQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_DOMAINS, Transport.call("domains.iterate").query(query).options(options)); + } + + /** + * Adds a sending domain. + * + * @param body the request body + * @return the response + */ + public DomainData create(StoreDomainData body) { + return create(body, null); + } + + /** + * Adds a sending domain. + * + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public DomainData create(StoreDomainData body, RequestOptions options) { + return transport.call(Operations.CREATE_DOMAIN, Transport.call("domains.create").body(body).options(options)); + } + + /** + * Retrieves a domain; {@code include} can add its DNS records. + * + * @param domainId the domain id + * @return the response + */ + public DomainData retrieve(String domainId) { + return retrieve(domainId, null, null); + } + + /** + * Retrieves a domain; {@code include} can add its DNS records. + * + * @param domainId the domain id + * @param query the query parameters, or null + * @return the response + */ + public DomainData retrieve(String domainId, GetDomainQuery query) { + return retrieve(domainId, query, null); + } + + /** + * Retrieves a domain; {@code include} can add its DNS records. + * + * @param domainId the domain id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public DomainData retrieve(String domainId, GetDomainQuery query, RequestOptions options) { + return transport.call(Operations.GET_DOMAIN, Transport.call("domains.retrieve").path(domainId).query(query).options(options)); + } + + /** + * Deletes a domain. + * + * @param domainId the domain id + * @return the response + */ + public MessageResponse delete(String domainId) { + return delete(domainId, null); + } + + /** + * Deletes a domain. + * + * @param domainId the domain id + * @param options per-call options, or null + * @return the response + */ + public MessageResponse delete(String domainId, RequestOptions options) { + return transport.call(Operations.DELETE_DOMAIN, Transport.call("domains.delete").path(domainId).options(options)); + } + + /** + * Checks every DNS record of the domain. + * + * @param domainId the domain id + * @return the response + */ + public DnsVerificationSuccessResponse verifyDnsRecords(String domainId) { + return verifyDnsRecords(domainId, null); + } + + /** + * Checks every DNS record of the domain. + * + * @param domainId the domain id + * @param options per-call options, or null + * @return the response + */ + public DnsVerificationSuccessResponse verifyDnsRecords(String domainId, RequestOptions options) { + return transport.call(Operations.VERIFY_DOMAIN_DNS_RECORDS, Transport.call("domains.verifyDnsRecords").path(domainId).options(options)); + } + + /** + * Checks one DNS record of the domain. + * + * @param domainId the domain id + * @param recordId the record id + * @return the response + */ + public MessageResponse verifyDnsRecord(String domainId, String recordId) { + return verifyDnsRecord(domainId, recordId, null); + } + + /** + * Checks one DNS record of the domain. + * + * @param domainId the domain id + * @param recordId the record id + * @param options per-call options, or null + * @return the response + */ + public MessageResponse verifyDnsRecord(String domainId, String recordId, RequestOptions options) { + return transport.call(Operations.VERIFY_DOMAIN_DNS_RECORD, Transport.call("domains.verifyDnsRecord").path(domainId, recordId).options(options)); + } + + /** + * Replaces the projects that may send from the domain. + * + * @param domainId the domain id + * @param body the request body + * @return the response + */ + public DomainMutationResponse updateProjects(String domainId, UpdateDomainProjectsData body) { + return updateProjects(domainId, body, null); + } + + /** + * Replaces the projects that may send from the domain. + * + * @param domainId the domain id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public DomainMutationResponse updateProjects(String domainId, UpdateDomainProjectsData body, RequestOptions options) { + return transport.call(Operations.UPDATE_DOMAIN_PROJECTS, Transport.call("domains.updateProjects").path(domainId).body(body).options(options)); + } + + @Override + public String toString() { + return "Domains{}"; + } +} diff --git a/src/main/java/co/lettermint/EmailAttachment.java b/src/main/java/co/lettermint/EmailAttachment.java new file mode 100644 index 0000000..0b14dae --- /dev/null +++ b/src/main/java/co/lettermint/EmailAttachment.java @@ -0,0 +1,112 @@ +package co.lettermint; + +import co.lettermint.exceptions.LettermintValidationException; +import java.util.Base64; + +/** + * An attachment. Immutable: {@link #contentType(String)} and {@link #contentId(String)} return a copy. + * + *

{@code
+ * EmailAttachment.of("invoice.pdf", Files.readAllBytes(path)).contentType("application/pdf");
+ * EmailAttachment.ofBase64("logo.png", logoBase64).contentId("logo");  // 
+ * }
+ */ +public final class EmailAttachment { + private final String filename; + private final byte[] bytes; + private final String base64; + private final String contentType; + private final String contentId; + + private EmailAttachment(String filename, byte[] bytes, String base64, String contentType, String contentId) { + this.filename = filename; + this.bytes = bytes; + this.base64 = base64; + this.contentType = contentType; + this.contentId = contentId; + } + + private static String checkFilename(String filename) { + if (filename == null || filename.isEmpty()) { + throw new LettermintValidationException("An attachment needs a filename.", "attachments"); + } + return filename; + } + + /** + * @param filename the file name, for example {@code invoice.pdf} + * @param content the raw bytes; the SDK copies them and base64-encodes them when sending + * @return the attachment + */ + public static EmailAttachment of(String filename, byte[] content) { + checkFilename(filename); + if (content == null) { + throw new LettermintValidationException("Attachment content must not be null.", "attachments"); + } + return new EmailAttachment(filename, content.clone(), null, null, null); + } + + /** + * @param filename the file name, for example {@code logo.png} + * @param base64 the content, already base64-encoded + * @return the attachment + */ + public static EmailAttachment ofBase64(String filename, String base64) { + checkFilename(filename); + if (base64 == null) { + throw new LettermintValidationException("Attachment content must not be null.", "attachments"); + } + return new EmailAttachment(filename, null, base64, null, null); + } + + /** + * @param contentType the MIME type, for example {@code application/pdf}; detected by the API when null + * @return a copy with this content type + */ + public EmailAttachment contentType(String contentType) { + return new EmailAttachment(filename, bytes, base64, contentType, contentId); + } + + /** + * @param contentId the Content-ID of an inline image referenced as {@code cid:}, or null + * @return a copy with this Content-ID + */ + public EmailAttachment contentId(String contentId) { + return new EmailAttachment(filename, bytes, base64, contentType, contentId); + } + + /** + * @return the file name + */ + public String filename() { + return filename; + } + + /** + * @return the MIME type, or null + */ + public String contentType() { + return contentType; + } + + /** + * @return the Content-ID, or null + */ + public String contentId() { + return contentId; + } + + /** + * @return the content, base64-encoded + */ + public String base64Content() { + return base64 != null ? base64 : Base64.getEncoder().encodeToString(bytes); + } + + @Override + public String toString() { + return "EmailAttachment{filename=" + filename + + (contentType != null ? ", contentType=" + contentType : "") + + (contentId != null ? ", contentId=" + contentId : "") + "}"; + } +} diff --git a/src/main/java/co/lettermint/EmailBuilder.java b/src/main/java/co/lettermint/EmailBuilder.java new file mode 100644 index 0000000..a9bf294 --- /dev/null +++ b/src/main/java/co/lettermint/EmailBuilder.java @@ -0,0 +1,250 @@ +package co.lettermint; + +import co.lettermint.types.MessageTagInput; +import co.lettermint.types.SandboxResult; +import co.lettermint.types.SendMailRequestSettings; +import co.lettermint.types.SendMailResponse; +import java.time.Instant; +import java.util.Collection; +import java.util.Map; + +/** + * An immutable email builder bound to a client, created by {@code lettermint.emails().compose()}. + * + *

Every setter returns a new builder and leaves this one unchanged, so a base builder can be kept + * and reused as a template, also across threads. A setter that throws leaves the builder unchanged. + * Keep the returned builder when you build an email over several statements: + * + *

{@code
+ * EmailBuilder email = lettermint.emails().compose().from("hello@acme.com").to(user.email()).subject("Your invoice");
+ * if (user.accountant() != null) {
+ *     email = email.cc(user.accountant());
+ * }
+ * email.html(invoiceHtml).send();
+ * }
+ */ +public final class EmailBuilder { + private final Emails emails; + private final EmailMessage message; + + EmailBuilder(Emails emails, EmailMessage message) { + this.emails = emails; + this.message = message; + } + + /** + * @param from the sender, for example {@code Acme } + * @return a new builder + */ + public EmailBuilder from(String from) { + return new EmailBuilder(emails, message.from(from)); + } + + /** + * @param to the recipients; replaces the list + * @return a new builder + */ + public EmailBuilder to(String... to) { + return new EmailBuilder(emails, message.to(to)); + } + + /** + * @param to the recipients; replaces the list + * @return a new builder + */ + public EmailBuilder to(Collection to) { + return new EmailBuilder(emails, message.to(to)); + } + + /** + * @param cc the CC recipients; replaces the list + * @return a new builder + */ + public EmailBuilder cc(String... cc) { + return new EmailBuilder(emails, message.cc(cc)); + } + + /** + * @param cc the CC recipients; replaces the list, null removes it + * @return a new builder + */ + public EmailBuilder cc(Collection cc) { + return new EmailBuilder(emails, message.cc(cc)); + } + + /** + * @param bcc the BCC recipients; replaces the list + * @return a new builder + */ + public EmailBuilder bcc(String... bcc) { + return new EmailBuilder(emails, message.bcc(bcc)); + } + + /** + * @param bcc the BCC recipients; replaces the list, null removes it + * @return a new builder + */ + public EmailBuilder bcc(Collection bcc) { + return new EmailBuilder(emails, message.bcc(bcc)); + } + + /** + * @param replyTo the Reply-To addresses; replaces the list + * @return a new builder + */ + public EmailBuilder replyTo(String... replyTo) { + return new EmailBuilder(emails, message.replyTo(replyTo)); + } + + /** + * @param replyTo the Reply-To addresses; replaces the list, null removes it + * @return a new builder + */ + public EmailBuilder replyTo(Collection replyTo) { + return new EmailBuilder(emails, message.replyTo(replyTo)); + } + + /** + * @param subject the subject line + * @return a new builder + */ + public EmailBuilder subject(String subject) { + return new EmailBuilder(emails, message.subject(subject)); + } + + /** + * @param html the HTML body; null removes it + * @return a new builder + */ + public EmailBuilder html(String html) { + return new EmailBuilder(emails, message.html(html)); + } + + /** + * @param text the plain-text body; null removes it + * @return a new builder + */ + public EmailBuilder text(String text) { + return new EmailBuilder(emails, message.text(text)); + } + + /** + * @param headers custom email headers; replaces them, null removes them + * @return a new builder + */ + public EmailBuilder headers(Map headers) { + return new EmailBuilder(emails, message.headers(headers)); + } + + /** + * @param metadata data stored with the message, not added as headers + * @return a new builder + */ + public EmailBuilder metadata(Map metadata) { + return new EmailBuilder(emails, message.metadata(metadata)); + } + + /** + * @param tag the legacy single tag; null removes it + * @return a new builder + */ + public EmailBuilder tag(String tag) { + return new EmailBuilder(emails, message.tag(tag)); + } + + /** + * @param tags name/value tags (see {@link EmailMessage#tags(MessageTagInput...)}); replaces them + * @return a new builder + */ + public EmailBuilder tags(MessageTagInput... tags) { + return new EmailBuilder(emails, message.tags(tags)); + } + + /** + * @param tags name/value tags; replaces them, null removes them + * @return a new builder + */ + public EmailBuilder tags(Collection tags) { + return new EmailBuilder(emails, message.tags(tags)); + } + + /** + * @param route the slug of the route to send through + * @return a new builder + */ + public EmailBuilder route(String route) { + return new EmailBuilder(emails, message.route(route)); + } + + /** + * @param scheduledAt the delivery time: ISO 8601 or English such as {@code tomorrow 9am}; null removes it + * @return a new builder + */ + public EmailBuilder scheduledAt(String scheduledAt) { + return new EmailBuilder(emails, message.scheduledAt(scheduledAt)); + } + + /** + * @param scheduledAt the delivery time, sent as ISO 8601 in UTC + * @return a new builder + */ + public EmailBuilder scheduledAt(Instant scheduledAt) { + return new EmailBuilder(emails, message.scheduledAt(scheduledAt)); + } + + /** + * @param settings per-email settings that override the route settings + * @return a new builder + */ + public EmailBuilder settings(SendMailRequestSettings settings) { + return new EmailBuilder(emails, message.settings(settings)); + } + + /** + * @param sandboxResult the result a Sandbox project simulates for every recipient + * @return a new builder + */ + public EmailBuilder sandboxResult(SandboxResult sandboxResult) { + return new EmailBuilder(emails, message.sandboxResult(sandboxResult)); + } + + /** + * @param attachment the attachment to add + * @return a new builder + */ + public EmailBuilder attach(EmailAttachment attachment) { + return new EmailBuilder(emails, message.attach(attachment)); + } + + /** + * @return the email as an {@link EmailMessage}, for example for {@code emails().sendBatch()} + */ + public EmailMessage build() { + return message; + } + + /** + * Sends this email. The builder stays unchanged and can be sent again. + * + * @return the message id and status + */ + public SendMailResponse send() { + return emails.send(message, null); + } + + /** + * Sends this email with options, such as an idempotency key. + * + * @param options the idempotency key and timeout of this call, or null + * @return the message id and status + */ + public SendMailResponse send(SendOptions options) { + return emails.send(message, options); + } + + /** The email, without attachment content. Contains no credentials. */ + @Override + public String toString() { + return "EmailBuilder{" + message + "}"; + } +} diff --git a/src/main/java/co/lettermint/EmailMessage.java b/src/main/java/co/lettermint/EmailMessage.java new file mode 100644 index 0000000..4af4ed3 --- /dev/null +++ b/src/main/java/co/lettermint/EmailMessage.java @@ -0,0 +1,475 @@ +package co.lettermint; + +import co.lettermint.types.MessageAttachmentInput; +import co.lettermint.types.MessageTagInput; +import co.lettermint.types.SandboxResult; +import co.lettermint.types.SendMailRequest; +import co.lettermint.types.SendMailRequestSettings; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.StringJoiner; + +/** + * An email. Immutable and thread-safe: every setter returns a new message and leaves this one + * unchanged, so a message can be shared and reused as a template. A setter that throws leaves the + * message unchanged. + * + *
{@code
+ * EmailMessage message = EmailMessage.create()
+ *     .from("Acme ")
+ *     .to("jane@example.com")
+ *     .subject("Welcome to Acme")
+ *     .html("

Thanks for signing up.

"); + * lettermint.emails().send(message); + * }
+ * + *

Each setter has an accessor of the same name without arguments: {@code message.subject()}. + * {@code to}, {@code cc}, {@code bcc} and {@code replyTo} replace their list; {@link #attach} appends. + */ +public final class EmailMessage { + private static final EmailMessage EMPTY = new EmailMessage(new Fields()); + + /** The values; every collection is unmodifiable, so a shallow copy is a full copy. */ + private static final class Fields implements Cloneable { + String from; + List to = List.of(); + List cc; + List bcc; + List replyTo; + String subject; + String html; + String text; + Map headers; + Map metadata; + String tag; + List tags; + String route; + String scheduledAt; + SendMailRequestSettings settings; + SandboxResult sandboxResult; + List attachments; + + @Override + protected Fields clone() { + try { + return (Fields) super.clone(); + } catch (CloneNotSupportedException error) { + throw new AssertionError(error); + } + } + } + + @FunctionalInterface + private interface Change { + void apply(Fields fields); + } + + private final Fields fields; + + private EmailMessage(Fields fields) { + this.fields = fields; + } + + /** + * @return an empty message + */ + public static EmailMessage create() { + return EMPTY; + } + + private EmailMessage with(Change change) { + Fields copy = fields.clone(); + change.apply(copy); + EmailMessage message = new EmailMessage(copy); + EmailValidation.validate(message, ""); + return message; + } + + private static List list(Collection values) { + return values == null ? null : Collections.unmodifiableList(new ArrayList<>(values)); + } + + private static List list(String[] values) { + return values == null ? null : list(Arrays.asList(values)); + } + + private static Map map(Map values) { + return values == null ? null : Collections.unmodifiableMap(new LinkedHashMap<>(values)); + } + + /** + * @param from the sender, for example {@code Acme } + * @return a copy with this sender + */ + public EmailMessage from(String from) { + return with(f -> f.from = from); + } + + /** + * @param to the recipients; replaces the list + * @return a copy with these recipients + */ + public EmailMessage to(String... to) { + List value = list(to); + return with(f -> f.to = value == null ? List.of() : value); + } + + /** + * @param to the recipients; replaces the list + * @return a copy with these recipients + */ + public EmailMessage to(Collection to) { + List value = list(to); + return with(f -> f.to = value == null ? List.of() : value); + } + + /** + * @param cc the CC recipients; replaces the list + * @return a copy with these CC recipients + */ + public EmailMessage cc(String... cc) { + List value = list(cc); + return with(f -> f.cc = value); + } + + /** + * @param cc the CC recipients; replaces the list, null removes it + * @return a copy with these CC recipients + */ + public EmailMessage cc(Collection cc) { + List value = list(cc); + return with(f -> f.cc = value); + } + + /** + * @param bcc the BCC recipients; replaces the list + * @return a copy with these BCC recipients + */ + public EmailMessage bcc(String... bcc) { + List value = list(bcc); + return with(f -> f.bcc = value); + } + + /** + * @param bcc the BCC recipients; replaces the list, null removes it + * @return a copy with these BCC recipients + */ + public EmailMessage bcc(Collection bcc) { + List value = list(bcc); + return with(f -> f.bcc = value); + } + + /** + * @param replyTo the Reply-To addresses; replaces the list + * @return a copy with these Reply-To addresses + */ + public EmailMessage replyTo(String... replyTo) { + List value = list(replyTo); + return with(f -> f.replyTo = value); + } + + /** + * @param replyTo the Reply-To addresses; replaces the list, null removes it + * @return a copy with these Reply-To addresses + */ + public EmailMessage replyTo(Collection replyTo) { + List value = list(replyTo); + return with(f -> f.replyTo = value); + } + + /** + * @param subject the subject line + * @return a copy with this subject + */ + public EmailMessage subject(String subject) { + return with(f -> f.subject = subject); + } + + /** + * @param html the HTML body; null removes it + * @return a copy with this HTML body + */ + public EmailMessage html(String html) { + return with(f -> f.html = html); + } + + /** + * @param text the plain-text body; null removes it + * @return a copy with this text body + */ + public EmailMessage text(String text) { + return with(f -> f.text = text); + } + + /** + * @param headers custom email headers; replaces them, null removes them + * @return a copy with these headers + */ + public EmailMessage headers(Map headers) { + Map value = map(headers); + return with(f -> f.headers = value); + } + + /** + * @param metadata data stored with the message, not added as headers; replaces it, null removes it + * @return a copy with this metadata + */ + public EmailMessage metadata(Map metadata) { + Map value = map(metadata); + return with(f -> f.metadata = value); + } + + /** + * @param tag the legacy single tag; null removes it + * @return a copy with this tag + */ + public EmailMessage tag(String tag) { + return with(f -> f.tag = tag); + } + + /** + * Name/value tags: up to 20, or 19 with a legacy {@link #tag(String)}. Names match + * {@code ^[A-Za-z0-9_-]{1,32}$}, do not start with {@code __lettermint} and are unique; values match + * {@code ^[A-Za-z0-9_-]{1,64}$}. + * + * @param tags the tags, for example {@code new MessageTagInput("campaign", "welcome")}; replaces them + * @return a copy with these tags + * @throws co.lettermint.exceptions.LettermintValidationException when a tag is invalid + */ + public EmailMessage tags(MessageTagInput... tags) { + return tags(tags == null ? null : Arrays.asList(tags)); + } + + /** + * @param tags the tags; replaces them, null removes them + * @return a copy with these tags + * @see #tags(MessageTagInput...) + */ + public EmailMessage tags(Collection tags) { + List value = tags == null ? null : Collections.unmodifiableList(new ArrayList<>(tags)); + return with(f -> f.tags = value); + } + + /** + * @param route the slug of the route to send through; null removes it + * @return a copy with this route + */ + public EmailMessage route(String route) { + return with(f -> f.route = route); + } + + /** + * @param scheduledAt the delivery time: ISO 8601, or English such as {@code tomorrow 9am}; null + * removes it + * @return a copy with this delivery time + */ + public EmailMessage scheduledAt(String scheduledAt) { + return with(f -> f.scheduledAt = scheduledAt); + } + + /** + * @param scheduledAt the delivery time, sent as ISO 8601 in UTC + * @return a copy with this delivery time + */ + public EmailMessage scheduledAt(Instant scheduledAt) { + return scheduledAt(scheduledAt == null ? null : scheduledAt.toString()); + } + + /** + * @param settings per-email settings that override the route settings; null removes them + * @return a copy with these settings + */ + public EmailMessage settings(SendMailRequestSettings settings) { + return with(f -> f.settings = settings); + } + + /** + * @param sandboxResult the result a Sandbox project simulates for every recipient; null removes it + * @return a copy with this result + */ + public EmailMessage sandboxResult(SandboxResult sandboxResult) { + return with(f -> f.sandboxResult = sandboxResult); + } + + /** + * @param attachment the attachment to add + * @return a copy with the attachment appended + */ + public EmailMessage attach(EmailAttachment attachment) { + Objects.requireNonNull(attachment, "attachment"); + return with(f -> { + List next = new ArrayList<>(f.attachments == null ? List.of() : f.attachments); + next.add(attachment); + f.attachments = Collections.unmodifiableList(next); + }); + } + + /** @return the sender, or null */ + public String from() { + return fields.from; + } + + /** @return the recipients (unmodifiable, possibly empty) */ + public List to() { + return fields.to; + } + + /** @return the CC recipients, or null */ + public List cc() { + return fields.cc; + } + + /** @return the BCC recipients, or null */ + public List bcc() { + return fields.bcc; + } + + /** @return the Reply-To addresses, or null */ + public List replyTo() { + return fields.replyTo; + } + + /** @return the subject, or null */ + public String subject() { + return fields.subject; + } + + /** @return the HTML body, or null */ + public String html() { + return fields.html; + } + + /** @return the plain-text body, or null */ + public String text() { + return fields.text; + } + + /** @return the custom headers, or null */ + public Map headers() { + return fields.headers; + } + + /** @return the metadata, or null */ + public Map metadata() { + return fields.metadata; + } + + /** @return the legacy tag, or null */ + public String tag() { + return fields.tag; + } + + /** @return the name/value tags, or null */ + public List tags() { + return fields.tags; + } + + /** @return the route slug, or null */ + public String route() { + return fields.route; + } + + /** @return the delivery time, or null */ + public String scheduledAt() { + return fields.scheduledAt; + } + + /** @return the per-email settings, or null */ + public SendMailRequestSettings settings() { + return fields.settings; + } + + /** @return the simulated Sandbox result, or null */ + public SandboxResult sandboxResult() { + return fields.sandboxResult; + } + + /** @return the attachments (unmodifiable, possibly empty) */ + public List attachments() { + return fields.attachments == null ? List.of() : fields.attachments; + } + + /** + * @return the message in the API's wire format, with attachments base64-encoded + */ + public SendMailRequest toRequest() { + SendMailRequest.Builder request = SendMailRequest.builder() + .from(fields.from) + .to(fields.to) + .cc(fields.cc) + .bcc(fields.bcc) + .replyTo(fields.replyTo) + .subject(fields.subject) + .headers(fields.headers) + .metadata(fields.metadata) + .tags(fields.tags) + .route(fields.route) + .scheduledAt(fields.scheduledAt) + .settings(fields.settings) + .sandboxResult(fields.sandboxResult); + // Optional and nullable on the wire: set only when present, so that nothing is sent as null. + if (fields.html != null) { + request.html(fields.html); + } + if (fields.text != null) { + request.text(fields.text); + } + if (fields.tag != null) { + request.tag(fields.tag); + } + if (fields.attachments != null) { + List attachments = new ArrayList<>(); + for (EmailAttachment attachment : fields.attachments) { + MessageAttachmentInput.Builder input = MessageAttachmentInput.builder() + .filename(attachment.filename()) + .content(attachment.base64Content()); + if (attachment.contentType() != null) { + input.contentType(attachment.contentType()); + } + if (attachment.contentId() != null) { + input.contentId(attachment.contentId()); + } + attachments.add(input.build()); + } + request.attachments(attachments); + } + return request.build(); + } + + /** The message without attachment content. Contains no credentials. */ + @Override + public String toString() { + StringJoiner joiner = new StringJoiner(", ", "EmailMessage{", "}"); + add(joiner, "from", fields.from); + add(joiner, "to", fields.to.isEmpty() ? null : fields.to); + add(joiner, "cc", fields.cc); + add(joiner, "bcc", fields.bcc); + add(joiner, "replyTo", fields.replyTo); + add(joiner, "subject", fields.subject); + add(joiner, "html", fields.html == null ? null : "(" + fields.html.length() + " characters)"); + add(joiner, "text", fields.text == null ? null : "(" + fields.text.length() + " characters)"); + add(joiner, "headers", fields.headers); + add(joiner, "metadata", fields.metadata); + add(joiner, "tag", fields.tag); + add(joiner, "tags", fields.tags); + add(joiner, "route", fields.route); + add(joiner, "scheduledAt", fields.scheduledAt); + add(joiner, "settings", fields.settings); + add(joiner, "sandboxResult", fields.sandboxResult); + add(joiner, "attachments", fields.attachments); + return joiner.toString(); + } + + private static void add(StringJoiner joiner, String name, Object value) { + if (value != null) { + joiner.add(name + "=" + value); + } + } +} diff --git a/src/main/java/co/lettermint/EmailValidation.java b/src/main/java/co/lettermint/EmailValidation.java new file mode 100644 index 0000000..76f3fa7 --- /dev/null +++ b/src/main/java/co/lettermint/EmailValidation.java @@ -0,0 +1,58 @@ +package co.lettermint; + +import co.lettermint.exceptions.LettermintValidationException; +import co.lettermint.types.MessageTagInput; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Pattern; + +/** + * The checks the SDK makes before a request, shared by {@code emails().send()}, + * {@code emails().sendBatch()}, {@link EmailMessage} and {@link EmailBuilder}. Pure: it only throws. + */ +final class EmailValidation { + private static final Pattern TAG_NAME = Pattern.compile("^[A-Za-z0-9_-]{1,32}$"); + private static final Pattern TAG_VALUE = Pattern.compile("^[A-Za-z0-9_-]{1,64}$"); + private static final int MAX_TAGS = 20; + + private EmailValidation() { + } + + static void validate(EmailMessage message, String prefix) { + String field = prefix.isEmpty() ? "tags" : prefix + ".tags"; + String legacyTag = message.tag(); + validateTags(message.tags(), legacyTag != null && !legacyTag.isEmpty(), field); + } + + static void validateTags(List tags, boolean hasLegacyTag, String field) { + if (tags == null) { + return; + } + int maximum = hasLegacyTag ? MAX_TAGS - 1 : MAX_TAGS; + if (tags.size() > maximum) { + throw new LettermintValidationException(hasLegacyTag + ? "A legacy tag and no more than " + maximum + " message tags are permitted." + : "No more than " + maximum + " message tags are permitted.", field); + } + Set names = new HashSet<>(); + for (MessageTagInput tag : tags) { + if (tag == null || tag.name() == null || tag.value() == null) { + throw new LettermintValidationException("Message tags must have a name and a value.", field); + } + if (!TAG_NAME.matcher(tag.name()).matches()) { + throw new LettermintValidationException("Message tag names must match ^[A-Za-z0-9_-]{1,32}$.", field); + } + if (tag.name().toLowerCase(Locale.ROOT).startsWith("__lettermint")) { + throw new LettermintValidationException("Message tag names must not start with __lettermint.", field); + } + if (!TAG_VALUE.matcher(tag.value()).matches()) { + throw new LettermintValidationException("Message tag values must match ^[A-Za-z0-9_-]{1,64}$.", field); + } + if (!names.add(tag.name())) { + throw new LettermintValidationException("Message tag names must be unique (case-sensitive).", field); + } + } + } +} diff --git a/src/main/java/co/lettermint/Emails.java b/src/main/java/co/lettermint/Emails.java new file mode 100644 index 0000000..b32c072 --- /dev/null +++ b/src/main/java/co/lettermint/Emails.java @@ -0,0 +1,125 @@ +package co.lettermint; + +import co.lettermint.exceptions.LettermintValidationException; +import co.lettermint.types.Operations; +import co.lettermint.types.Operations.AuthSurface; +import co.lettermint.types.SendMailRequest; +import co.lettermint.types.SendMailResponse; +import java.util.ArrayList; +import java.util.List; + +/** + * Sends email with the project sending token ({@code x-lettermint-token}). Holds no message state: + * every call sends exactly what it is given. Thread-safe. + */ +public final class Emails { + private final Transport transport; + + Emails(Transport transport) { + this.transport = transport; + } + + /** + * Sends one email. + * + * @param message the email + * @return the message id and status + */ + public SendMailResponse send(EmailMessage message) { + return send(message, null); + } + + /** + * Sends one email. + * + * @param message the email + * @param options the idempotency key and timeout of this call, or null + * @return the message id and status + */ + public SendMailResponse send(EmailMessage message, SendOptions options) { + transport.assertAuth("emails.send", AuthSurface.SENDING); + if (message == null) { + throw new LettermintValidationException("send() takes an EmailMessage.", "message"); + } + EmailValidation.validate(message, ""); + return transport.call(Operations.SEND_MAIL, Transport.call("emails.send").body(message.toRequest()).options(options)); + } + + /** + * Sends up to 500 emails in one request. Use {@link EmailBuilder#build()} for builders. + * + * @param messages the emails + * @return one result per email, in order + */ + public List sendBatch(List messages) { + return sendBatch(messages, null); + } + + /** + * Sends up to 500 emails in one request. + * + * @param messages the emails + * @param options the idempotency key and timeout of this call, or null + * @return one result per email, in order + */ + public List sendBatch(List messages, SendOptions options) { + transport.assertAuth("emails.sendBatch", AuthSurface.SENDING); + if (messages == null) { + throw new LettermintValidationException("sendBatch() takes a list of messages.", "messages"); + } + List body = new ArrayList<>(messages.size()); + for (int index = 0; index < messages.size(); index++) { + EmailMessage message = messages.get(index); + if (message == null) { + throw new LettermintValidationException("An email message must not be null.", "messages[" + index + "]"); + } + EmailValidation.validate(message, "messages[" + index + "]"); + body.add(message.toRequest()); + } + return transport.call(Operations.SEND_BATCH_MAIL, Transport.call("emails.sendBatch").body(body).options(options)); + } + + /** + * Starts an immutable email builder. Every setter returns a new builder. + * + * @return an empty builder bound to this client + */ + public EmailBuilder compose() { + return compose(EmailMessage.create()); + } + + /** + * Starts an immutable email builder from a message. + * + * @param message the message to start from + * @return a builder bound to this client + */ + public EmailBuilder compose(EmailMessage message) { + transport.assertAuth("emails.compose", AuthSurface.SENDING); + EmailValidation.validate(message == null ? EmailMessage.create() : message, ""); + return new EmailBuilder(this, message == null ? EmailMessage.create() : message); + } + + /** + * Checks the sending token: {@code GET /ping} returns {@code pong}. + * + * @return {@code pong} + */ + public String ping() { + return ping(null); + } + + /** + * @param options per-call options, or null + * @return {@code pong} + * @see #ping() + */ + public String ping(RequestOptions options) { + return transport.call(Operations.PING, Transport.call("emails.ping").auth(AuthSurface.SENDING).options(options)).trim(); + } + + @Override + public String toString() { + return "Emails{}"; + } +} diff --git a/src/main/java/co/lettermint/Lettermint.java b/src/main/java/co/lettermint/Lettermint.java index ccdd12d..e0a01fc 100644 --- a/src/main/java/co/lettermint/Lettermint.java +++ b/src/main/java/co/lettermint/Lettermint.java @@ -1,79 +1,305 @@ package co.lettermint; -import co.lettermint.api.ApiClient; -import co.lettermint.client.LettermintClient; -import co.lettermint.endpoints.EmailEndpoint; +import co.lettermint.exceptions.LettermintConfigException; +import co.lettermint.types.AnalyticsQuery; +import co.lettermint.types.AnalyticsResponse; +import co.lettermint.types.BlockedFileTypes; +import co.lettermint.types.Operations; +import java.net.http.HttpClient; +import java.time.Duration; /** - * Main entry point for the Lettermint Java SDK. + * The Lettermint client. * - *

Example usage:

*
{@code
- * Lettermint lettermint = new Lettermint("your-api-token");
+ * Lettermint lettermint = Lettermint.builder()
+ *     .sendingToken(System.getenv("LETTERMINT_PROJECT_TOKEN"))
+ *     .teamToken(System.getenv("LETTERMINT_TEAM_TOKEN"))
+ *     .build();
  *
- * SendEmailResponse response = lettermint.email()
- *     .from("sender@example.com")
- *     .to("recipient@example.com")
- *     .subject("Hello")
- *     .html("

Hello World

") - * .send(); + * Lettermint lettermint = Lettermint.of("lm_..."); // team or sending token, detected by prefix * }
+ * + *

{@link #emails()} uses the sending token; every other part uses the team token. {@link #ping()}, + * {@code messages().reschedule()} and {@code messages().cancel()} accept either. The client holds no + * message state, is immutable and thread-safe: create it once and share it. */ -public class Lettermint { +public final class Lettermint { + private final Transport transport; + private final Emails emails; + private final Domains domains; + private final Messages messages; + private final Projects projects; + private final Routes routes; + private final Stats stats; + private final Suppressions suppressions; + private final Team team; + private final Webhooks webhooks; - private final LettermintClient client; + private Lettermint(Transport transport) { + this.transport = transport; + this.emails = new Emails(transport); + this.domains = new Domains(transport); + this.messages = new Messages(transport); + this.projects = new Projects(transport); + this.routes = new Routes(transport); + this.stats = new Stats(transport); + this.suppressions = new Suppressions(transport); + this.team = new Team(transport); + this.webhooks = new Webhooks(transport); + } /** - * Create a new Lettermint instance with the default API base URL. - * - * @param apiToken Your Lettermint API token + * @return a builder for a client */ - public Lettermint(String apiToken) { - this(apiToken, null); + public static Builder builder() { + return new Builder(); } /** - * Create a new Lettermint instance with a custom API base URL. + * Creates a client from one token with the default options. {@code lm_team_} followed by letters + * and digits is a team token; {@code lm_} followed by letters and digits is a sending token. * - * @param apiToken Your Lettermint API token - * @param baseUrl Custom API base URL (e.g., "https://custom-url.com/v1") + * @param token a team or sending token + * @return the client + * @throws LettermintConfigException for any other format, such as an SSO token ({@code lm_sso_...}); + * the message never contains the token */ - public Lettermint(String apiToken, String baseUrl) { - this.client = new LettermintClient(apiToken, baseUrl); + public static Lettermint of(String token) { + return builder().token(token).build(); } /** - * Get a new email endpoint for sending emails. - * Each call returns a fresh instance for thread-safety. - * - * @return A new email endpoint with fluent builder methods + * @return sending email, with the sending token + */ + public Emails emails() { + return emails; + } + + /** + * @return sending domains, with the team token + */ + public Domains domains() { + return domains; + } + + /** + * @return sent and received messages, with the team token + */ + public Messages messages() { + return messages; + } + + /** + * @return projects and their report forwarding, with the team token */ - public EmailEndpoint email() { - return new EmailEndpoint(client); + public Projects projects() { + return projects; } - public static EmailEndpoint email(String apiToken) { - return email(apiToken, null); + /** + * @return routes of a project, with the team token + */ + public Routes routes() { + return routes; + } + + /** + * @return sending statistics, with the team token + */ + public Stats stats() { + return stats; } - public static EmailEndpoint email(String apiToken, String baseUrl) { - return new EmailEndpoint(new LettermintClient(apiToken, baseUrl, LettermintClient.AuthMode.SENDING)); + /** + * @return the suppression list, with the team token + */ + public Suppressions suppressions() { + return suppressions; } - public static ApiClient api(String apiToken) { - return api(apiToken, null); + /** + * @return the team and its members, with the team token + */ + public Team team() { + return team; } - public static ApiClient api(String apiToken, String baseUrl) { - return new ApiClient(apiToken, baseUrl); + /** + * @return webhook endpoints and their deliveries, with the team token + */ + public Webhooks webhooks() { + return webhooks; } /** - * Get the underlying HTTP client. + * Checks the configured token: {@code GET /ping} returns {@code pong}. Uses the team token when + * configured, otherwise the sending token. * - * @return The Lettermint HTTP client + * @return {@code pong} + */ + public String ping() { + return ping(null); + } + + /** + * @param options per-call options, or null + * @return {@code pong} + * @see #ping() */ - public LettermintClient getClient() { - return client; + public String ping(RequestOptions options) { + return transport.call(Operations.PING, Transport.call("ping").options(options)).trim(); + } + + /** + * Queries email analytics. Needs the team token. + * + * @param query the metrics, dimensions and filters + * @return the analytics + */ + public AnalyticsResponse analytics(AnalyticsQuery query) { + return analytics(query, null); + } + + /** + * @param query the metrics, dimensions and filters + * @param options per-call options, or null + * @return the analytics + * @see #analytics(AnalyticsQuery) + */ + public AnalyticsResponse analytics(AnalyticsQuery query, RequestOptions options) { + return transport.call(Operations.QUERY_ANALYTICS, Transport.call("analytics").body(query).options(options)); + } + + /** + * The file extensions and MIME types that cannot be attached. Needs the team token. + * + * @return the blocked file types + */ + public BlockedFileTypes blockedFileTypes() { + return blockedFileTypes(null); + } + + /** + * @param options per-call options, or null + * @return the blocked file types + * @see #blockedFileTypes() + */ + public BlockedFileTypes blockedFileTypes(RequestOptions options) { + return transport.call(Operations.LIST_BLOCKED_FILE_TYPES, Transport.call("blockedFileTypes").options(options)); + } + + /** The configuration without credentials: tokens are shown as {@code [redacted]}. */ + @Override + public String toString() { + return "Lettermint{baseUrl=" + transport.baseUrl() + + ", timeout=" + transport.timeout() + + ", sendingToken=" + (transport.hasSendingToken() ? Secret.REDACTED : "null") + + ", teamToken=" + (transport.hasTeamToken() ? Secret.REDACTED : "null") + "}"; + } + + /** Builds a {@link Lettermint} client. Pass at least one token. Not thread-safe. */ + public static final class Builder { + private Secret sendingToken; + private Secret teamToken; + private String baseUrl = Transport.DEFAULT_BASE_URL; + private Duration timeout = Transport.DEFAULT_TIMEOUT; + private HttpClient httpClient; + + private Builder() { + } + + /** + * @param sendingToken a project sending token ({@code lm_...}), sent as {@code x-lettermint-token} + * by {@code emails()} + * @return this builder + */ + public Builder sendingToken(String sendingToken) { + this.sendingToken = Tokens.check("sendingToken", sendingToken); + return this; + } + + /** + * @param teamToken a team API token ({@code lm_team_...}), sent as {@code Authorization: Bearer} + * by the Team API + * @return this builder + */ + public Builder teamToken(String teamToken) { + this.teamToken = Tokens.check("teamToken", teamToken); + return this; + } + + /** + * Sets {@link #teamToken(String)} or {@link #sendingToken(String)} by the token's format; see + * {@link Lettermint#of(String)}. + * + * @param token a team or sending token + * @return this builder + * @throws LettermintConfigException for an unrecognised format + */ + public Builder token(String token) { + return Tokens.detect(token) == Tokens.Kind.TEAM ? teamToken(token) : sendingToken(token); + } + + /** + * @param baseUrl the API base URL; default {@code https://api.lettermint.co/v1} + * @return this builder + */ + public Builder baseUrl(String baseUrl) { + this.baseUrl = Transport.checkBaseUrl(baseUrl); + return this; + } + + /** + * @param timeout the request timeout, covering the whole request including reading the body; + * default 30 seconds + * @return this builder + */ + public Builder timeout(Duration timeout) { + this.timeout = Transport.checkTimeout(timeout, "timeout"); + return this; + } + + /** + * Uses your {@link HttpClient}, for example for a proxy, TLS settings or an executor. It must not + * follow redirects ({@code followRedirects(HttpClient.Redirect.NEVER)}, the JDK default), so + * tokens never reach another host. The default client also uses the timeout to connect. + * + * @param httpClient the HTTP client + * @return this builder + */ + public Builder httpClient(HttpClient httpClient) { + if (httpClient == null) { + throw new LettermintConfigException("httpClient must not be null."); + } + if (httpClient.followRedirects() != HttpClient.Redirect.NEVER) { + throw new LettermintConfigException( + "httpClient must not follow redirects; build it with followRedirects(HttpClient.Redirect.NEVER)."); + } + this.httpClient = httpClient; + return this; + } + + /** + * @return the client + * @throws LettermintConfigException when neither token is set + */ + public Lettermint build() { + if (sendingToken == null && teamToken == null) { + throw new LettermintConfigException("Pass sendingToken, teamToken or both."); + } + HttpClient client = httpClient != null + ? httpClient + : HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NEVER).connectTimeout(timeout).build(); + return new Lettermint(new Transport(sendingToken, teamToken, client, baseUrl, timeout)); + } + + /** The configuration without credentials. */ + @Override + public String toString() { + return "Lettermint.Builder{baseUrl=" + baseUrl + ", timeout=" + timeout + + ", sendingToken=" + (sendingToken != null ? Secret.REDACTED : "null") + + ", teamToken=" + (teamToken != null ? Secret.REDACTED : "null") + "}"; + } } } diff --git a/src/main/java/co/lettermint/Messages.java b/src/main/java/co/lettermint/Messages.java new file mode 100644 index 0000000..818e8f5 --- /dev/null +++ b/src/main/java/co/lettermint/Messages.java @@ -0,0 +1,301 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.ListMessageEventsQuery; +import co.lettermint.types.ListMessagesQuery; +import co.lettermint.types.MessageData; +import co.lettermint.types.MessageEventData; +import co.lettermint.types.MessageListData; +import co.lettermint.types.Operations; +import co.lettermint.types.ProcessInboundMessageResponse; +import co.lettermint.types.RescheduleMessageRequest; +import co.lettermint.types.ScheduledMessage; + +/** Sent and received messages. Needs the team token; {@code reschedule} and {@code cancel} also accept the sending token when no team token is configured. Thread-safe. */ +public final class Messages { + private final Transport transport; + + Messages(Transport transport) { + this.transport = transport; + } + + /** + * Lists messages, one page at a time. + * + * @return the response + */ + public CursorPage list() { + return list(null, null); + } + + /** + * Lists messages, one page at a time. + * + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(ListMessagesQuery query) { + return list(query, null); + } + + /** + * Lists messages, one page at a time. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(ListMessagesQuery query, RequestOptions options) { + return transport.call(Operations.LIST_MESSAGES, Transport.call("messages.list").query(query).options(options)); + } + + /** + * Iterates over every message, following {@code next_cursor}. + * + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate() { + return iterate(null, null); + } + + /** + * Iterates over every message, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListMessagesQuery query) { + return iterate(query, null); + } + + /** + * Iterates over every message, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListMessagesQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_MESSAGES, Transport.call("messages.iterate").query(query).options(options)); + } + + /** + * Retrieves a message. + * + * @param messageId the message id + * @return the response + */ + public MessageData retrieve(String messageId) { + return retrieve(messageId, null); + } + + /** + * Retrieves a message. + * + * @param messageId the message id + * @param options per-call options, or null + * @return the response + */ + public MessageData retrieve(String messageId, RequestOptions options) { + return transport.call(Operations.GET_MESSAGE, Transport.call("messages.retrieve").path(messageId).options(options)); + } + + /** + * Lists the events of a message, one page at a time. + * + * @param messageId the message id + * @return the response + */ + public CursorPage events(String messageId) { + return events(messageId, null, null); + } + + /** + * Lists the events of a message, one page at a time. + * + * @param messageId the message id + * @param query the query parameters, or null + * @return the response + */ + public CursorPage events(String messageId, ListMessageEventsQuery query) { + return events(messageId, query, null); + } + + /** + * Lists the events of a message, one page at a time. + * + * @param messageId the message id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage events(String messageId, ListMessageEventsQuery query, RequestOptions options) { + return transport.call(Operations.LIST_MESSAGE_EVENTS, Transport.call("messages.events").path(messageId).query(query).options(options)); + } + + /** + * Iterates over every event of a message, following {@code next_cursor}. + * + * @param messageId the message id + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterateEvents(String messageId) { + return iterateEvents(messageId, null, null); + } + + /** + * Iterates over every event of a message, following {@code next_cursor}. + * + * @param messageId the message id + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterateEvents(String messageId, ListMessageEventsQuery query) { + return iterateEvents(messageId, query, null); + } + + /** + * Iterates over every event of a message, following {@code next_cursor}. + * + * @param messageId the message id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterateEvents(String messageId, ListMessageEventsQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_MESSAGE_EVENTS, Transport.call("messages.iterateEvents").path(messageId).query(query).options(options)); + } + + /** + * The raw RFC 822 source. + * + * @param messageId the message id + * @return the body as text + */ + public String source(String messageId) { + return source(messageId, null); + } + + /** + * The raw RFC 822 source. + * + * @param messageId the message id + * @param options per-call options, or null + * @return the body as text + */ + public String source(String messageId, RequestOptions options) { + return transport.call(Operations.GET_MESSAGE_SOURCE, Transport.call("messages.source").path(messageId).options(options)); + } + + /** + * The HTML body. + * + * @param messageId the message id + * @return the body as text + */ + public String html(String messageId) { + return html(messageId, null); + } + + /** + * The HTML body. + * + * @param messageId the message id + * @param options per-call options, or null + * @return the body as text + */ + public String html(String messageId, RequestOptions options) { + return transport.call(Operations.GET_MESSAGE_HTML, Transport.call("messages.html").path(messageId).options(options)); + } + + /** + * The plain-text body. + * + * @param messageId the message id + * @return the body as text + */ + public String text(String messageId) { + return text(messageId, null); + } + + /** + * The plain-text body. + * + * @param messageId the message id + * @param options per-call options, or null + * @return the body as text + */ + public String text(String messageId, RequestOptions options) { + return transport.call(Operations.GET_MESSAGE_TEXT, Transport.call("messages.text").path(messageId).options(options)); + } + + /** + * Moves a scheduled message to another delivery time. Uses the team token if configured, otherwise the sending token. + * + * @param messageId the message id + * @param body the request body + * @return the response + */ + public ScheduledMessage reschedule(String messageId, RescheduleMessageRequest body) { + return reschedule(messageId, body, null); + } + + /** + * Moves a scheduled message to another delivery time. Uses the team token if configured, otherwise the sending token. + * + * @param messageId the message id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public ScheduledMessage reschedule(String messageId, RescheduleMessageRequest body, RequestOptions options) { + return transport.call(Operations.RESCHEDULE_MESSAGE, Transport.call("messages.reschedule").path(messageId).body(body).options(options)); + } + + /** + * Cancels a scheduled message. Uses the team token if configured, otherwise the sending token. + * + * @param messageId the message id + * @return the response + */ + public ScheduledMessage cancel(String messageId) { + return cancel(messageId, null); + } + + /** + * Cancels a scheduled message. Uses the team token if configured, otherwise the sending token. + * + * @param messageId the message id + * @param options per-call options, or null + * @return the response + */ + public ScheduledMessage cancel(String messageId, RequestOptions options) { + return transport.call(Operations.CANCEL_SCHEDULED_MESSAGE, Transport.call("messages.cancel").path(messageId).options(options)); + } + + /** + * Releases one quarantined inbound message for webhook delivery. Accepts an idempotency key. + * + * @param messageId the message id + * @return the response + */ + public ProcessInboundMessageResponse process(String messageId) { + return process(messageId, null); + } + + /** + * Releases one quarantined inbound message for webhook delivery. Accepts an idempotency key. + * + * @param messageId the message id + * @param options the idempotency key and timeout of this call, or null + * @return the response + */ + public ProcessInboundMessageResponse process(String messageId, SendOptions options) { + return transport.call(Operations.PROCESS_INBOUND_MESSAGE, Transport.call("messages.process").path(messageId).options(options)); + } + + @Override + public String toString() { + return "Messages{}"; + } +} diff --git a/src/main/java/co/lettermint/Projects.java b/src/main/java/co/lettermint/Projects.java new file mode 100644 index 0000000..6f42119 --- /dev/null +++ b/src/main/java/co/lettermint/Projects.java @@ -0,0 +1,220 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.GetProjectQuery; +import co.lettermint.types.ListProjectsQuery; +import co.lettermint.types.MessageResponse; +import co.lettermint.types.Operations; +import co.lettermint.types.ProjectCreatedData; +import co.lettermint.types.ProjectData; +import co.lettermint.types.ProjectListData; +import co.lettermint.types.ProjectMutationResponse; +import co.lettermint.types.RotateProjectTokenResponse; +import co.lettermint.types.StoreProjectData; +import co.lettermint.types.UpdateProjectData; + +/** Projects. Needs the team token. Thread-safe. */ +public final class Projects { + private final Transport transport; + private final ReportForwarding reportForwarding; + + Projects(Transport transport) { + this.transport = transport; + this.reportForwarding = new ReportForwarding(transport); + } + + /** + * @return report forwarding of a project + */ + public ReportForwarding reportForwarding() { + return reportForwarding; + } + + /** + * Lists projects, one page at a time. + * + * @return the response + */ + public CursorPage list() { + return list(null, null); + } + + /** + * Lists projects, one page at a time. + * + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(ListProjectsQuery query) { + return list(query, null); + } + + /** + * Lists projects, one page at a time. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(ListProjectsQuery query, RequestOptions options) { + return transport.call(Operations.LIST_PROJECTS, Transport.call("projects.list").query(query).options(options)); + } + + /** + * Iterates over every project, following {@code next_cursor}. + * + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate() { + return iterate(null, null); + } + + /** + * Iterates over every project, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListProjectsQuery query) { + return iterate(query, null); + } + + /** + * Iterates over every project, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListProjectsQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_PROJECTS, Transport.call("projects.iterate").query(query).options(options)); + } + + /** + * Creates a project. The response holds its sending token once ({@code apiToken}). + * + * @param body the request body + * @return the response + */ + public ProjectCreatedData create(StoreProjectData body) { + return create(body, null); + } + + /** + * Creates a project. The response holds its sending token once ({@code apiToken}). + * + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public ProjectCreatedData create(StoreProjectData body, RequestOptions options) { + return transport.call(Operations.CREATE_PROJECT, Transport.call("projects.create").body(body).options(options)); + } + + /** + * Retrieves a project. + * + * @param projectId the project id + * @return the response + */ + public ProjectData retrieve(String projectId) { + return retrieve(projectId, null, null); + } + + /** + * Retrieves a project. + * + * @param projectId the project id + * @param query the query parameters, or null + * @return the response + */ + public ProjectData retrieve(String projectId, GetProjectQuery query) { + return retrieve(projectId, query, null); + } + + /** + * Retrieves a project. + * + * @param projectId the project id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public ProjectData retrieve(String projectId, GetProjectQuery query, RequestOptions options) { + return transport.call(Operations.GET_PROJECT, Transport.call("projects.retrieve").path(projectId).query(query).options(options)); + } + + /** + * Updates a project. + * + * @param projectId the project id + * @param body the request body + * @return the response + */ + public ProjectMutationResponse update(String projectId, UpdateProjectData body) { + return update(projectId, body, null); + } + + /** + * Updates a project. + * + * @param projectId the project id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public ProjectMutationResponse update(String projectId, UpdateProjectData body, RequestOptions options) { + return transport.call(Operations.UPDATE_PROJECT, Transport.call("projects.update").path(projectId).body(body).options(options)); + } + + /** + * Deletes a project. + * + * @param projectId the project id + * @return the response + */ + public MessageResponse delete(String projectId) { + return delete(projectId, null); + } + + /** + * Deletes a project. + * + * @param projectId the project id + * @param options per-call options, or null + * @return the response + */ + public MessageResponse delete(String projectId, RequestOptions options) { + return transport.call(Operations.DELETE_PROJECT, Transport.call("projects.delete").path(projectId).options(options)); + } + + /** + * Rotates the project's legacy sending token. The API marks this endpoint as legacy. + * + * @param projectId the project id + * @return the response + * @deprecated The API marks this endpoint as legacy. + */ + @Deprecated + public RotateProjectTokenResponse rotateToken(String projectId) { + return rotateToken(projectId, null); + } + + /** + * Rotates the project's legacy sending token. The API marks this endpoint as legacy. + * + * @param projectId the project id + * @param options per-call options, or null + * @return the response + * @deprecated The API marks this endpoint as legacy. + */ + @Deprecated + public RotateProjectTokenResponse rotateToken(String projectId, RequestOptions options) { + return transport.call(Operations.ROTATE_PROJECT_TOKEN, Transport.call("projects.rotateToken").path(projectId).options(options)); + } + + @Override + public String toString() { + return "Projects{}"; + } +} diff --git a/src/main/java/co/lettermint/QueryString.java b/src/main/java/co/lettermint/QueryString.java new file mode 100644 index 0000000..13ab0b7 --- /dev/null +++ b/src/main/java/co/lettermint/QueryString.java @@ -0,0 +1,86 @@ +package co.lettermint; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Serializes query parameters to the API's bracket syntax, exactly like the Node SDK's + * {@code src/query.ts}: nested objects use {@code key[name]}, arrays of scalars are comma-joined, + * arrays of objects are indexed ({@code key[0][name]}), booleans are {@code 1}/{@code 0}, and null + * values are left out. Keys and values are form-encoded like {@code URLSearchParams}. + */ +final class QueryString { + private QueryString() { + } + + static String serialize(Map parameters, ObjectMapper mapper) { + if (parameters == null || parameters.isEmpty()) { + return ""; + } + List pairs = new ArrayList<>(); + for (Map.Entry entry : parameters.entrySet()) { + if (entry.getValue() != null) { + append(pairs, entry.getKey(), mapper.valueToTree(entry.getValue())); + } + } + StringBuilder query = new StringBuilder(); + for (String[] pair : pairs) { + if (query.length() > 0) { + query.append('&'); + } + query.append(encode(pair[0])).append('=').append(encode(pair[1])); + } + return query.toString(); + } + + private static void append(List pairs, String key, JsonNode value) { + if (value == null || value.isNull() || value.isMissingNode()) { + return; + } + if (value.isArray()) { + boolean scalars = true; + for (JsonNode item : value) { + scalars &= item.isValueNode() || item.isNull(); + } + if (scalars) { + List items = new ArrayList<>(); + for (JsonNode item : value) { + if (!item.isNull()) { + items.add(scalar(item)); + } + } + if (!items.isEmpty()) { + pairs.add(new String[] {key, String.join(",", items)}); + } + return; + } + for (int index = 0; index < value.size(); index++) { + append(pairs, key + "[" + index + "]", value.get(index)); + } + return; + } + if (value.isValueNode()) { + pairs.add(new String[] {key, scalar(value)}); + return; + } + for (Map.Entry field : value.properties()) { + append(pairs, key + "[" + field.getKey() + "]", field.getValue()); + } + } + + private static String scalar(JsonNode value) { + if (value.isBoolean()) { + return value.booleanValue() ? "1" : "0"; + } + return value.asText(); + } + + private static String encode(String value) { + return URLEncoder.encode(value, StandardCharsets.UTF_8); + } +} diff --git a/src/main/java/co/lettermint/ReportForwarding.java b/src/main/java/co/lettermint/ReportForwarding.java new file mode 100644 index 0000000..2f12e19 --- /dev/null +++ b/src/main/java/co/lettermint/ReportForwarding.java @@ -0,0 +1,130 @@ +package co.lettermint; + +import co.lettermint.types.GetReportForwardingResponse; +import co.lettermint.types.Operations; +import co.lettermint.types.ReportForwardingRequest; +import co.lettermint.types.ResendReportForwardingCodeResponse; +import co.lettermint.types.UpdateReportForwardingResponse; +import co.lettermint.types.VerifyReportForwardingRequest; +import co.lettermint.types.VerifyReportForwardingResponse; + +/** DMARC and complaint report forwarding of a project. Needs the team token. Thread-safe. */ +public final class ReportForwarding { + private final Transport transport; + + ReportForwarding(Transport transport) { + this.transport = transport; + } + + /** + * Retrieves the report forwarding settings. + * + * @param projectId the project id + * @return the response + */ + public GetReportForwardingResponse retrieve(String projectId) { + return retrieve(projectId, null); + } + + /** + * Retrieves the report forwarding settings. + * + * @param projectId the project id + * @param options per-call options, or null + * @return the response + */ + public GetReportForwardingResponse retrieve(String projectId, RequestOptions options) { + return transport.call(Operations.GET_REPORT_FORWARDING, Transport.call("projects.reportForwarding.retrieve").path(projectId).options(options)); + } + + /** + * Sets the forwarding destination. + * + * @param projectId the project id + * @param body the request body + * @return the response + */ + public UpdateReportForwardingResponse update(String projectId, ReportForwardingRequest body) { + return update(projectId, body, null); + } + + /** + * Sets the forwarding destination. + * + * @param projectId the project id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public UpdateReportForwardingResponse update(String projectId, ReportForwardingRequest body, RequestOptions options) { + return transport.call(Operations.UPDATE_REPORT_FORWARDING, Transport.call("projects.reportForwarding.update").path(projectId).body(body).options(options)); + } + + /** + * Disables report forwarding (HTTP 204). + * + * @param projectId the project id + */ + public void delete(String projectId) { + delete(projectId, null); + } + + /** + * Disables report forwarding (HTTP 204). + * + * @param projectId the project id + * @param options per-call options, or null + */ + public void delete(String projectId, RequestOptions options) { + transport.call(Operations.DELETE_REPORT_FORWARDING, Transport.call("projects.reportForwarding.delete").path(projectId).options(options)); + } + + /** + * Verifies the destination with the emailed code. + * + * @param projectId the project id + * @param body the request body + * @return the response + */ + public VerifyReportForwardingResponse verify(String projectId, VerifyReportForwardingRequest body) { + return verify(projectId, body, null); + } + + /** + * Verifies the destination with the emailed code. + * + * @param projectId the project id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public VerifyReportForwardingResponse verify(String projectId, VerifyReportForwardingRequest body, RequestOptions options) { + return transport.call(Operations.VERIFY_REPORT_FORWARDING, Transport.call("projects.reportForwarding.verify").path(projectId).body(body).options(options)); + } + + /** + * Sends the verification code again. + * + * @param projectId the project id + * @return the response + */ + public ResendReportForwardingCodeResponse resendCode(String projectId) { + return resendCode(projectId, null); + } + + /** + * Sends the verification code again. + * + * @param projectId the project id + * @param options per-call options, or null + * @return the response + */ + public ResendReportForwardingCodeResponse resendCode(String projectId, RequestOptions options) { + return transport.call(Operations.RESEND_REPORT_FORWARDING_CODE, Transport.call("projects.reportForwarding.resendCode").path(projectId).options(options)); + } + + @Override + public String toString() { + return "ReportForwarding{}"; + } +} diff --git a/src/main/java/co/lettermint/RequestOptions.java b/src/main/java/co/lettermint/RequestOptions.java new file mode 100644 index 0000000..728863c --- /dev/null +++ b/src/main/java/co/lettermint/RequestOptions.java @@ -0,0 +1,25 @@ +package co.lettermint; + +import java.time.Duration; + +/** + * Per-call options accepted by every SDK method that makes a request. + * + *

{@code
+ * lettermint.messages().list(query, RequestOptions.timeout(Duration.ofSeconds(5)));
+ * }
+ * + *

To cancel a call, interrupt the calling thread: the SDK aborts the request and throws + * {@link java.util.concurrent.CancellationException} with the thread's interrupt status set. + * + * @param timeout overrides the client's timeout for this call, or null for the client's timeout + */ +public record RequestOptions(Duration timeout) { + /** + * @param timeout the timeout for this call; it covers the whole request including the body + * @return options with this timeout + */ + public static RequestOptions timeout(Duration timeout) { + return new RequestOptions(timeout); + } +} diff --git a/src/main/java/co/lettermint/Routes.java b/src/main/java/co/lettermint/Routes.java new file mode 100644 index 0000000..a17fa0f --- /dev/null +++ b/src/main/java/co/lettermint/Routes.java @@ -0,0 +1,214 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.GetRouteQuery; +import co.lettermint.types.InboundDomainVerificationResponse; +import co.lettermint.types.ListRoutesQuery; +import co.lettermint.types.MessageResponse; +import co.lettermint.types.Operations; +import co.lettermint.types.RouteData; +import co.lettermint.types.RouteListData; +import co.lettermint.types.RouteMutationResponse; +import co.lettermint.types.StoreRouteData; +import co.lettermint.types.UpdateRouteData; + +/** Routes of a project. Needs the team token. Thread-safe. */ +public final class Routes { + private final Transport transport; + + Routes(Transport transport) { + this.transport = transport; + } + + /** + * Lists the routes of a project, one page at a time. + * + * @param projectId the project id + * @return the response + */ + public CursorPage list(String projectId) { + return list(projectId, null, null); + } + + /** + * Lists the routes of a project, one page at a time. + * + * @param projectId the project id + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(String projectId, ListRoutesQuery query) { + return list(projectId, query, null); + } + + /** + * Lists the routes of a project, one page at a time. + * + * @param projectId the project id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(String projectId, ListRoutesQuery query, RequestOptions options) { + return transport.call(Operations.LIST_ROUTES, Transport.call("routes.list").path(projectId).query(query).options(options)); + } + + /** + * Iterates over every route of a project, following {@code next_cursor}. + * + * @param projectId the project id + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(String projectId) { + return iterate(projectId, null, null); + } + + /** + * Iterates over every route of a project, following {@code next_cursor}. + * + * @param projectId the project id + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(String projectId, ListRoutesQuery query) { + return iterate(projectId, query, null); + } + + /** + * Iterates over every route of a project, following {@code next_cursor}. + * + * @param projectId the project id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(String projectId, ListRoutesQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_ROUTES, Transport.call("routes.iterate").path(projectId).query(query).options(options)); + } + + /** + * Creates a route in a project. + * + * @param projectId the project id + * @param body the request body + * @return the response + */ + public RouteMutationResponse create(String projectId, StoreRouteData body) { + return create(projectId, body, null); + } + + /** + * Creates a route in a project. + * + * @param projectId the project id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public RouteMutationResponse create(String projectId, StoreRouteData body, RequestOptions options) { + return transport.call(Operations.CREATE_ROUTE, Transport.call("routes.create").path(projectId).body(body).options(options)); + } + + /** + * Retrieves a route. + * + * @param routeId the route id + * @return the response + */ + public RouteData retrieve(String routeId) { + return retrieve(routeId, null, null); + } + + /** + * Retrieves a route. + * + * @param routeId the route id + * @param query the query parameters, or null + * @return the response + */ + public RouteData retrieve(String routeId, GetRouteQuery query) { + return retrieve(routeId, query, null); + } + + /** + * Retrieves a route. + * + * @param routeId the route id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public RouteData retrieve(String routeId, GetRouteQuery query, RequestOptions options) { + return transport.call(Operations.GET_ROUTE, Transport.call("routes.retrieve").path(routeId).query(query).options(options)); + } + + /** + * Updates a route. + * + * @param routeId the route id + * @param body the request body + * @return the response + */ + public RouteMutationResponse update(String routeId, UpdateRouteData body) { + return update(routeId, body, null); + } + + /** + * Updates a route. + * + * @param routeId the route id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public RouteMutationResponse update(String routeId, UpdateRouteData body, RequestOptions options) { + return transport.call(Operations.UPDATE_ROUTE, Transport.call("routes.update").path(routeId).body(body).options(options)); + } + + /** + * Deletes a route. + * + * @param routeId the route id + * @return the response + */ + public MessageResponse delete(String routeId) { + return delete(routeId, null); + } + + /** + * Deletes a route. + * + * @param routeId the route id + * @param options per-call options, or null + * @return the response + */ + public MessageResponse delete(String routeId, RequestOptions options) { + return transport.call(Operations.DELETE_ROUTE, Transport.call("routes.delete").path(routeId).options(options)); + } + + /** + * Checks the DNS of the route's inbound domain. + * + * @param routeId the route id + * @return the response + */ + public InboundDomainVerificationResponse verifyInboundDomain(String routeId) { + return verifyInboundDomain(routeId, null); + } + + /** + * Checks the DNS of the route's inbound domain. + * + * @param routeId the route id + * @param options per-call options, or null + * @return the response + */ + public InboundDomainVerificationResponse verifyInboundDomain(String routeId, RequestOptions options) { + return transport.call(Operations.VERIFY_ROUTE_INBOUND_DOMAIN, Transport.call("routes.verifyInboundDomain").path(routeId).options(options)); + } + + @Override + public String toString() { + return "Routes{}"; + } +} diff --git a/src/main/java/co/lettermint/Secret.java b/src/main/java/co/lettermint/Secret.java new file mode 100644 index 0000000..bd99aad --- /dev/null +++ b/src/main/java/co/lettermint/Secret.java @@ -0,0 +1,24 @@ +package co.lettermint; + +/** + * A credential. {@code toString()} never shows it, so reflective dumps and string concatenation print + * {@code [redacted]}; only the transport reads the value. + */ +final class Secret { + static final String REDACTED = "[redacted]"; + + private final String value; + + Secret(String value) { + this.value = value; + } + + String reveal() { + return value; + } + + @Override + public String toString() { + return REDACTED; + } +} diff --git a/src/main/java/co/lettermint/SendOptions.java b/src/main/java/co/lettermint/SendOptions.java new file mode 100644 index 0000000..1c20b2f --- /dev/null +++ b/src/main/java/co/lettermint/SendOptions.java @@ -0,0 +1,51 @@ +package co.lettermint; + +import java.time.Duration; + +/** + * Options of calls that accept an {@code Idempotency-Key}: {@code emails().send()}, + * {@code emails().sendBatch()}, {@code EmailBuilder.send()} and {@code messages().process()}. + * + *

{@code
+ * lettermint.emails().send(message, SendOptions.idempotencyKey("order-1234-confirmation"));
+ * }
+ * + *

The key applies only to the call it is passed to; the SDK never stores it. Retrying with the same + * key does not send the email again. The SDK never retries on its own. + * + * @param idempotencyKey sent as the {@code Idempotency-Key} header, or null + * @param timeout overrides the client's timeout for this call, or null + */ +public record SendOptions(String idempotencyKey, Duration timeout) { + /** + * @param idempotencyKey sent as the {@code Idempotency-Key} header + * @return options with this key + */ + public static SendOptions idempotencyKey(String idempotencyKey) { + return new SendOptions(idempotencyKey, null); + } + + /** + * @param timeout the timeout for this call + * @return options with this timeout + */ + public static SendOptions timeout(Duration timeout) { + return new SendOptions(null, timeout); + } + + /** + * @param idempotencyKey sent as the {@code Idempotency-Key} header + * @return a copy with this key + */ + public SendOptions withIdempotencyKey(String idempotencyKey) { + return new SendOptions(idempotencyKey, timeout); + } + + /** + * @param timeout the timeout for this call + * @return a copy with this timeout + */ + public SendOptions withTimeout(Duration timeout) { + return new SendOptions(idempotencyKey, timeout); + } +} diff --git a/src/main/java/co/lettermint/Stats.java b/src/main/java/co/lettermint/Stats.java new file mode 100644 index 0000000..8b7fc6c --- /dev/null +++ b/src/main/java/co/lettermint/Stats.java @@ -0,0 +1,40 @@ +package co.lettermint; + +import co.lettermint.types.GetStatsQuery; +import co.lettermint.types.Operations; +import co.lettermint.types.StatsData; + +/** Sending statistics. Needs the team token. Thread-safe. */ +public final class Stats { + private final Transport transport; + + Stats(Transport transport) { + this.transport = transport; + } + + /** + * Daily statistics between {@code from} and {@code to} (Y-m-d, at most 90 days). + * + * @param query the query parameters + * @return the response + */ + public StatsData retrieve(GetStatsQuery query) { + return retrieve(query, null); + } + + /** + * Daily statistics between {@code from} and {@code to} (Y-m-d, at most 90 days). + * + * @param query the query parameters + * @param options per-call options, or null + * @return the response + */ + public StatsData retrieve(GetStatsQuery query, RequestOptions options) { + return transport.call(Operations.GET_STATS, Transport.call("stats.retrieve").query(query).options(options)); + } + + @Override + public String toString() { + return "Stats{}"; + } +} diff --git a/src/main/java/co/lettermint/Suppressions.java b/src/main/java/co/lettermint/Suppressions.java new file mode 100644 index 0000000..4d7886e --- /dev/null +++ b/src/main/java/co/lettermint/Suppressions.java @@ -0,0 +1,125 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.DeleteSuppressionResponse; +import co.lettermint.types.ListSuppressionsQuery; +import co.lettermint.types.Operations; +import co.lettermint.types.StoreSuppressionData; +import co.lettermint.types.SuppressedRecipientData; +import co.lettermint.types.SuppressionStoreResponse; + +/** The suppression list. Needs the team token. Thread-safe. */ +public final class Suppressions { + private final Transport transport; + + Suppressions(Transport transport) { + this.transport = transport; + } + + /** + * Lists suppressions, one page at a time. + * + * @return the response + */ + public CursorPage list() { + return list(null, null); + } + + /** + * Lists suppressions, one page at a time. + * + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(ListSuppressionsQuery query) { + return list(query, null); + } + + /** + * Lists suppressions, one page at a time. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(ListSuppressionsQuery query, RequestOptions options) { + return transport.call(Operations.LIST_SUPPRESSIONS, Transport.call("suppressions.list").query(query).options(options)); + } + + /** + * Iterates over every suppression, following {@code next_cursor}. + * + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate() { + return iterate(null, null); + } + + /** + * Iterates over every suppression, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListSuppressionsQuery query) { + return iterate(query, null); + } + + /** + * Iterates over every suppression, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListSuppressionsQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_SUPPRESSIONS, Transport.call("suppressions.iterate").query(query).options(options)); + } + + /** + * Suppresses one or more recipients. + * + * @param body the request body + * @return the response + */ + public SuppressionStoreResponse create(StoreSuppressionData body) { + return create(body, null); + } + + /** + * Suppresses one or more recipients. + * + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public SuppressionStoreResponse create(StoreSuppressionData body, RequestOptions options) { + return transport.call(Operations.CREATE_SUPPRESSIONS, Transport.call("suppressions.create").body(body).options(options)); + } + + /** + * Removes a suppression, or opens a review ticket for it. + * + * @param suppressionId the suppression id + * @return the response + */ + public DeleteSuppressionResponse delete(String suppressionId) { + return delete(suppressionId, null); + } + + /** + * Removes a suppression, or opens a review ticket for it. + * + * @param suppressionId the suppression id + * @param options per-call options, or null + * @return the response + */ + public DeleteSuppressionResponse delete(String suppressionId, RequestOptions options) { + return transport.call(Operations.DELETE_SUPPRESSION, Transport.call("suppressions.delete").path(suppressionId).options(options)); + } + + @Override + public String toString() { + return "Suppressions{}"; + } +} diff --git a/src/main/java/co/lettermint/Team.java b/src/main/java/co/lettermint/Team.java new file mode 100644 index 0000000..c05351f --- /dev/null +++ b/src/main/java/co/lettermint/Team.java @@ -0,0 +1,121 @@ +package co.lettermint; + +import co.lettermint.types.GetTeamQuery; +import co.lettermint.types.Operations; +import co.lettermint.types.TeamData; +import co.lettermint.types.TeamMutationResponse; +import co.lettermint.types.TeamRoleListResponse; +import co.lettermint.types.TeamUsageDetailData; +import co.lettermint.types.UpdateTeamData; + +/** The team of the token. Needs the team token. Thread-safe. */ +public final class Team { + private final Transport transport; + private final TeamMembers members; + + Team(Transport transport) { + this.transport = transport; + this.members = new TeamMembers(transport); + } + + /** + * @return team members + */ + public TeamMembers members() { + return members; + } + + /** + * Retrieves the team; {@code include} can add its features. + * + * @return the response + */ + public TeamData retrieve() { + return retrieve(null, null); + } + + /** + * Retrieves the team; {@code include} can add its features. + * + * @param query the query parameters, or null + * @return the response + */ + public TeamData retrieve(GetTeamQuery query) { + return retrieve(query, null); + } + + /** + * Retrieves the team; {@code include} can add its features. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public TeamData retrieve(GetTeamQuery query, RequestOptions options) { + return transport.call(Operations.GET_TEAM, Transport.call("team.retrieve").query(query).options(options)); + } + + /** + * Updates the team. + * + * @param body the request body + * @return the response + */ + public TeamMutationResponse update(UpdateTeamData body) { + return update(body, null); + } + + /** + * Updates the team. + * + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public TeamMutationResponse update(UpdateTeamData body, RequestOptions options) { + return transport.call(Operations.UPDATE_TEAM, Transport.call("team.update").body(body).options(options)); + } + + /** + * Usage of the current and previous billing periods. + * + * @return the response + */ + public TeamUsageDetailData usage() { + return usage(null); + } + + /** + * Usage of the current and previous billing periods. + * + * @param options per-call options, or null + * @return the response + */ + public TeamUsageDetailData usage(RequestOptions options) { + return transport.call(Operations.GET_TEAM_USAGE, Transport.call("team.usage").options(options)); + } + + /** + * The roles that can be assigned to members. + * + * @return the response + */ + public TeamRoleListResponse roles() { + return roles(null); + } + + /** + * The roles that can be assigned to members. + * + * @param options per-call options, or null + * @return the response + */ + public TeamRoleListResponse roles(RequestOptions options) { + return transport.call(Operations.LIST_TEAM_ROLES, Transport.call("team.roles").options(options)); + } + + @Override + public String toString() { + return "Team{}"; + } +} diff --git a/src/main/java/co/lettermint/TeamMembers.java b/src/main/java/co/lettermint/TeamMembers.java new file mode 100644 index 0000000..eab51e9 --- /dev/null +++ b/src/main/java/co/lettermint/TeamMembers.java @@ -0,0 +1,125 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.ListTeamMembersQuery; +import co.lettermint.types.Operations; +import co.lettermint.types.TeamMemberData; +import co.lettermint.types.UpdateTeamMemberAssignmentData; + +/** Team members. Needs the team token. Thread-safe. */ +public final class TeamMembers { + private final Transport transport; + + TeamMembers(Transport transport) { + this.transport = transport; + } + + /** + * Lists team members, one page at a time. + * + * @return the response + */ + public CursorPage list() { + return list(null, null); + } + + /** + * Lists team members, one page at a time. + * + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(ListTeamMembersQuery query) { + return list(query, null); + } + + /** + * Lists team members, one page at a time. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(ListTeamMembersQuery query, RequestOptions options) { + return transport.call(Operations.LIST_TEAM_MEMBERS, Transport.call("team.members.list").query(query).options(options)); + } + + /** + * Iterates over every team member, following {@code next_cursor}. + * + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate() { + return iterate(null, null); + } + + /** + * Iterates over every team member, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListTeamMembersQuery query) { + return iterate(query, null); + } + + /** + * Iterates over every team member, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListTeamMembersQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_TEAM_MEMBERS, Transport.call("team.members.iterate").query(query).options(options)); + } + + /** + * Retrieves a team member. + * + * @param userId the user id + * @return the response + */ + public TeamMemberData retrieve(String userId) { + return retrieve(userId, null); + } + + /** + * Retrieves a team member. + * + * @param userId the user id + * @param options per-call options, or null + * @return the response + */ + public TeamMemberData retrieve(String userId, RequestOptions options) { + return transport.call(Operations.GET_TEAM_MEMBER, Transport.call("team.members.retrieve").path(userId).options(options)); + } + + /** + * Changes a member's role and project access. + * + * @param userId the user id + * @param body the request body + * @return the response + */ + public TeamMemberData updateAssignment(String userId, UpdateTeamMemberAssignmentData body) { + return updateAssignment(userId, body, null); + } + + /** + * Changes a member's role and project access. + * + * @param userId the user id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public TeamMemberData updateAssignment(String userId, UpdateTeamMemberAssignmentData body, RequestOptions options) { + return transport.call(Operations.UPDATE_TEAM_MEMBER_ASSIGNMENT, Transport.call("team.members.updateAssignment").path(userId).body(body).options(options)); + } + + @Override + public String toString() { + return "TeamMembers{}"; + } +} diff --git a/src/main/java/co/lettermint/Tokens.java b/src/main/java/co/lettermint/Tokens.java new file mode 100644 index 0000000..04a1f29 --- /dev/null +++ b/src/main/java/co/lettermint/Tokens.java @@ -0,0 +1,50 @@ +package co.lettermint; + +import co.lettermint.exceptions.LettermintConfigException; +import java.util.regex.Pattern; + +/** Token formats: {@code ApiToken::TEAM_PREFIX} and {@code ::PROJECT_PREFIX} in the Lettermint backend. */ +final class Tokens { + /** Team API tokens. Checked first: every team token also starts with {@code lm_}. */ + private static final Pattern TEAM = Pattern.compile("^lm_team_[0-9A-Za-z]+$"); + /** Project sending tokens (32 or 22 random characters). */ + private static final Pattern SENDING = Pattern.compile("^lm_[0-9A-Za-z]+$"); + /** Characters allowed in a token, so that it is a valid HTTP header value. */ + private static final Pattern HEADER_SAFE = Pattern.compile("^[\\x21-\\x7e]+$"); + + enum Kind { + SENDING, + TEAM + } + + private Tokens() { + } + + /** Classifies a token passed as {@code Lettermint.of(token)}. The message never contains the token. */ + static Kind detect(String token) { + if (token != null) { + if (TEAM.matcher(token).matches()) { + return Kind.TEAM; + } + if (SENDING.matcher(token).matches()) { + return Kind.SENDING; + } + } + throw new LettermintConfigException( + "Unrecognised token format; pass sendingToken(...) or teamToken(...) to Lettermint.builder() instead."); + } + + /** Validates an explicitly configured token; null means not set. */ + static Secret check(String option, String token) { + if (token == null) { + return null; + } + if (token.isEmpty()) { + throw new LettermintConfigException(option + " must be a non-empty string."); + } + if (!HEADER_SAFE.matcher(token).matches()) { + throw new LettermintConfigException(option + " contains whitespace or characters that are not allowed in an HTTP header."); + } + return new Secret(token); + } +} diff --git a/src/main/java/co/lettermint/Transport.java b/src/main/java/co/lettermint/Transport.java new file mode 100644 index 0000000..b1a6028 --- /dev/null +++ b/src/main/java/co/lettermint/Transport.java @@ -0,0 +1,443 @@ +package co.lettermint; + +import co.lettermint.exceptions.ApiException; +import co.lettermint.exceptions.AuthenticationException; +import co.lettermint.exceptions.ConflictException; +import co.lettermint.exceptions.ConnectionException; +import co.lettermint.exceptions.LettermintConfigException; +import co.lettermint.exceptions.LettermintException; +import co.lettermint.exceptions.LettermintValidationException; +import co.lettermint.exceptions.NotFoundException; +import co.lettermint.exceptions.PermissionException; +import co.lettermint.exceptions.RateLimitException; +import co.lettermint.exceptions.RedirectException; +import co.lettermint.exceptions.ServerException; +import co.lettermint.exceptions.TimeoutException; +import co.lettermint.exceptions.UnexpectedResponseException; +import co.lettermint.exceptions.ValidationException; +import co.lettermint.types.CursorPage; +import co.lettermint.types.Operations.AuthSurface; +import co.lettermint.types.Operations.Operation; +import co.lettermint.types.Operations.ResponseKind; +import co.lettermint.types.QueryParameters; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpTimeoutException; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Sends requests for one client. Holds the tokens; nothing outside this package can read them. + * Immutable and thread-safe. + */ +final class Transport { + static final String DEFAULT_BASE_URL = "https://api.lettermint.co/v1"; + static final Duration DEFAULT_TIMEOUT = Duration.ofSeconds(30); + static final String USER_AGENT = "lettermint-java/" + BuildInfo.VERSION; + static final ObjectMapper MAPPER = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + private static final Pattern PLACEHOLDER = Pattern.compile("\\{(\\w+)}"); + private static final Pattern DIGITS = Pattern.compile("^\\d+$"); + private static final TypeReference>> FIELD_ERRORS = new TypeReference<>() {}; + + private final Secret sendingToken; + private final Secret teamToken; + private final HttpClient http; + private final String baseUrl; + private final Duration timeout; + + Transport(Secret sendingToken, Secret teamToken, HttpClient http, String baseUrl, Duration timeout) { + this.sendingToken = sendingToken; + this.teamToken = teamToken; + this.http = http; + this.baseUrl = baseUrl; + this.timeout = timeout; + } + + String baseUrl() { + return baseUrl; + } + + Duration timeout() { + return timeout; + } + + boolean hasSendingToken() { + return sendingToken != null; + } + + boolean hasTeamToken() { + return teamToken != null; + } + + // ------------------------------------------------------------ checks + static Duration checkTimeout(Duration value, String option) { + if (value == null || value.isNegative() || value.isZero()) { + throw new LettermintConfigException(option + " must be a positive duration."); + } + return value; + } + + static String checkBaseUrl(String value) { + if (value == null) { + throw new LettermintConfigException("baseUrl must not be null."); + } + URI uri; + try { + uri = new URI(value); + } catch (URISyntaxException error) { + throw new LettermintConfigException("baseUrl must be an absolute http(s) URL."); + } + String scheme = uri.getScheme(); + if (scheme == null || !(scheme.equalsIgnoreCase("https") || scheme.equalsIgnoreCase("http")) || uri.getHost() == null) { + throw new LettermintConfigException("baseUrl must be an absolute http(s) URL."); + } + if (uri.getRawUserInfo() != null || uri.getRawQuery() != null || uri.getRawFragment() != null) { + throw new LettermintConfigException("baseUrl must not contain credentials, a query string or a fragment."); + } + return value.replaceAll("/+$", ""); + } + + /** Throws if the token for {@code auth} is not configured. */ + void assertAuth(String label, AuthSurface auth) { + authHeader(label, auth); + } + + private String[] authHeader(String label, AuthSurface auth) { + boolean useTeam = auth == AuthSurface.TEAM || (auth == AuthSurface.EITHER && teamToken != null); + if (useTeam) { + if (teamToken == null) { + throw new LettermintConfigException(label + " needs teamToken; set it with Lettermint.builder().teamToken(...)."); + } + return new String[] {"Authorization", "Bearer " + teamToken.reveal()}; + } + if (sendingToken == null) { + throw new LettermintConfigException(label + " needs sendingToken; set it with Lettermint.builder().sendingToken(...)."); + } + return new String[] {"x-lettermint-token", sendingToken.reveal()}; + } + + private static String encodePathParam(String label, String name, String value) { + if (value == null || value.isEmpty() || value.equals(".") || value.equals("..")) { + throw new LettermintConfigException(label + ": " + name + " must be a non-empty string other than \".\" and \"..\"."); + } + StringBuilder encoded = new StringBuilder(); + for (byte b : value.getBytes(StandardCharsets.UTF_8)) { + char c = (char) (b & 0xff); + // encodeURIComponent: unreserved characters plus !'()* + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || "-_.!~*'()".indexOf(c) >= 0) { + encoded.append(c); + } else { + encoded.append('%').append(Character.toUpperCase(Character.forDigit((b >> 4) & 0xf, 16))) + .append(Character.toUpperCase(Character.forDigit(b & 0xf, 16))); + } + } + return encoded.toString(); + } + + private static void checkIdempotencyKey(String key) { + boolean valid = !key.isEmpty(); + for (int i = 0; valid && i < key.length(); i++) { + char c = key.charAt(i); + valid = (c >= 0x20 || c == '\t') && c != 0x7f && c <= 0xff; + } + if (!valid) { + throw new LettermintValidationException("idempotencyKey must be a non-empty string without line breaks or control characters.", "idempotencyKey"); + } + } + + // ------------------------------------------------------------ calls + /** One call: the public method name for messages, path values in order, query, body and options. */ + static final class Call { + final String label; + String[] path = new String[0]; + QueryParameters query; + Object body; + String idempotencyKey; + Duration timeout; + AuthSurface auth; + + Call(String label) { + this.label = label; + } + + Call path(String... values) { + this.path = values; + return this; + } + + Call query(QueryParameters value) { + this.query = value; + return this; + } + + Call body(Object value) { + this.body = value; + return this; + } + + Call auth(AuthSurface value) { + this.auth = value; + return this; + } + + Call options(RequestOptions options) { + this.timeout = options == null ? null : options.timeout(); + return this; + } + + Call options(SendOptions options) { + this.timeout = options == null ? null : options.timeout(); + this.idempotencyKey = options == null ? null : options.idempotencyKey(); + return this; + } + } + + static Call call(String label) { + return new Call(label); + } + + R call(Operation operation, Call call) { + Prepared prepared = prepare(operation, call); + return execute(operation, call, prepared, call.query == null ? null : call.query.toParameters()); + } + + /** Follows {@code next_cursor} through every page. Checks the token and path eagerly. */ + CursorIterable paginate(Operation> operation, Call call) { + if (operation.pagination() == null) { + throw new IllegalStateException(operation.key() + " is not cursor-paginated"); + } + String cursorParam = operation.pagination().cursorParam(); + Prepared prepared = prepare(operation, call); + return new CursorIterable<>(cursor -> { + Map parameters = call.query == null ? new LinkedHashMap<>() : call.query.toParameters(); + if (cursor != null) { + if (cursorParam.indexOf('[') < 0) { + parameters.remove(cursorParam); // like the Node SDK: a flat cursor goes last + } + parameters.put(cursorParam, cursor); + } + CursorPage page = execute(operation, call, prepared, parameters); + if (page == null || page.data() == null) { + throw new UnexpectedResponseException(call.label + ": the API returned a page without a data array.", 200, ""); + } + return page; + }); + } + + private record Prepared(String path, String[] auth, Duration timeout) { + } + + private Prepared prepare(Operation operation, Call call) { + String[] auth = authHeader(call.label, call.auth != null ? call.auth : operation.auth()); + List names = operation.pathParams(); + if (call.path.length != names.size()) { + throw new IllegalStateException(call.label + ": expected " + names.size() + " path parameters"); + } + Matcher matcher = PLACEHOLDER.matcher(operation.path()); + StringBuilder path = new StringBuilder(); + while (matcher.find()) { + int index = names.indexOf(matcher.group(1)); + matcher.appendReplacement(path, Matcher.quoteReplacement(encodePathParam(call.label, matcher.group(1), call.path[index]))); + } + matcher.appendTail(path); + Duration timeout = call.timeout == null ? this.timeout : checkTimeout(call.timeout, "timeout"); + if (call.idempotencyKey != null) { + checkIdempotencyKey(call.idempotencyKey); + } + return new Prepared(path.toString(), auth, timeout); + } + + private R execute(Operation operation, Call call, Prepared prepared, Map parameters) { + String query = QueryString.serialize(parameters, MAPPER); + URI uri = URI.create(baseUrl + prepared.path() + (query.isEmpty() ? "" : "?" + query)); + HttpRequest.Builder request = HttpRequest.newBuilder(uri) + .header("Accept", "application/json") + .header("User-Agent", USER_AGENT); + if (call.idempotencyKey != null) { + request.header("Idempotency-Key", call.idempotencyKey); + } + HttpRequest.BodyPublisher publisher = HttpRequest.BodyPublishers.noBody(); + if (call.body != null) { + try { + publisher = HttpRequest.BodyPublishers.ofByteArray(MAPPER.writeValueAsBytes(call.body)); + } catch (JsonProcessingException error) { + throw new LettermintException(call.label + ": the request body could not be encoded as JSON.", error); + } + request.header("Content-Type", "application/json"); + } + request.header(prepared.auth()[0], prepared.auth()[1]); + request.method(operation.method(), publisher); + + HttpResponse response = send(request.build(), prepared.timeout()); + int status = response.statusCode(); + if (status >= 300 && status < 400) { + throw new RedirectException(status); + } + String text = new String(response.body() == null ? new byte[0] : response.body(), StandardCharsets.UTF_8); + return decode(operation, response, status, text); + } + + private HttpResponse send(HttpRequest request, Duration timeout) { + CompletableFuture> future; + try { + future = http.sendAsync(request, HttpResponse.BodyHandlers.ofByteArray()); + } catch (IllegalArgumentException error) { + throw new ConnectionException(error); + } + try { + // The deadline covers connecting, sending, the headers and the whole body. + return future.get(timeout.toNanos(), TimeUnit.NANOSECONDS); + } catch (java.util.concurrent.TimeoutException error) { + future.cancel(true); + throw new TimeoutException(timeout); + } catch (InterruptedException error) { + future.cancel(true); + Thread.currentThread().interrupt(); + CancellationException cancelled = new CancellationException("The Lettermint request was cancelled because the thread was interrupted."); + cancelled.initCause(error); + throw cancelled; + } catch (ExecutionException error) { + Throwable cause = error.getCause(); + if (cause instanceof HttpTimeoutException) { + throw new TimeoutException(timeout); + } + throw new ConnectionException(cause); + } catch (CancellationException error) { + throw new ConnectionException(error); + } + } + + private static R decode(Operation operation, HttpResponse response, int status, String text) { + if (status >= 200 && status < 300) { + if (operation.responseKind() == ResponseKind.EMPTY || status == 204 || status == 205) { + return null; + } + if (operation.responseKind() == ResponseKind.TEXT) { + @SuppressWarnings("unchecked") + R result = (R) text; + return result; + } + if (text.isBlank()) { + throw new UnexpectedResponseException("The Lettermint API answered with HTTP " + status + " and an empty body where JSON was expected.", status, text); + } + JsonNode tree; + try { + tree = MAPPER.readTree(text); + } catch (JsonProcessingException error) { + throw new UnexpectedResponseException("The Lettermint API answered with HTTP " + status + " and a body that is not valid JSON.", status, text); + } + try { + return MAPPER.readerFor(MAPPER.getTypeFactory().constructType(operation.responseType())).readValue(tree); + } catch (IOException | IllegalArgumentException error) { + throw new UnexpectedResponseException("The Lettermint API answered with HTTP " + status + " and a body that does not match " + operation.key() + ".", status, text); + } + } + if (status < 400) { + throw new UnexpectedResponseException("The Lettermint API answered with an unexpected HTTP status " + status + ".", status, text); + } + JsonNode body = null; + if (!text.isBlank()) { + try { + body = MAPPER.readTree(text); + } catch (JsonProcessingException error) { + String contentType = response.headers().firstValue("content-type").map(value -> " (" + value.split(";")[0].trim() + ")").orElse(""); + throw new UnexpectedResponseException("The Lettermint API answered with HTTP " + status + " and a body that is not JSON" + contentType + ".", status, text); + } + } + throw apiException(status, body, response.headers().firstValue("retry-after").orElse(null)); + } + + static ApiException apiException(int status, JsonNode body, String retryAfter) { + String message = null; + String code = null; + Object details = null; + Map> errors = null; + if (body != null && body.isObject()) { + JsonNode error = body.get("error"); + if (error != null && error.isObject()) { + if (error.path("code").isTextual()) { + code = error.get("code").textValue(); + } + if (error.path("message").isTextual()) { + message = error.get("message").textValue(); + } + details = error.has("details") ? MAPPER.convertValue(error.get("details"), Object.class) : null; + } else if (error != null && error.isTextual()) { + code = error.textValue(); + } + if ((message == null || message.isEmpty()) && body.path("message").isTextual()) { + message = body.get("message").textValue(); + } + if (body.path("errors").isObject()) { + try { + errors = MAPPER.convertValue(body.get("errors"), FIELD_ERRORS); + } catch (IllegalArgumentException ignored) { + errors = null; + } + } + } + if (message == null || message.isEmpty()) { + message = "HTTP " + status; + } + Object decoded = body == null ? null : MAPPER.convertValue(body, Object.class); + switch (status) { + case 401: + return new AuthenticationException(status, message, code, details, decoded); + case 403: + return new PermissionException(status, message, code, details, decoded); + case 404: + return new NotFoundException(status, message, code, details, decoded); + case 409: + return new ConflictException(status, message, code, details, decoded); + case 422: + return new ValidationException(status, message, code, details, decoded, errors); + case 429: + return new RateLimitException(status, message, code, details, decoded, parseRetryAfter(retryAfter)); + default: + return status >= 500 ? new ServerException(status, message, code, details, decoded) : new ApiException(status, message, code, details, decoded); + } + } + + static Duration parseRetryAfter(String value) { + if (value == null || value.isBlank()) { + return null; + } + String trimmed = value.trim(); + if (DIGITS.matcher(trimmed).matches()) { + try { + return Duration.ofSeconds(Long.parseLong(trimmed)); + } catch (NumberFormatException error) { + return null; + } + } + try { + ZonedDateTime date = ZonedDateTime.parse(trimmed, DateTimeFormatter.RFC_1123_DATE_TIME); + long millis = date.toInstant().toEpochMilli() - System.currentTimeMillis(); + return Duration.ofSeconds(Math.max(0, (millis + 999) / 1000)); + } catch (DateTimeParseException error) { + return null; + } + } +} diff --git a/src/main/java/co/lettermint/Webhook.java b/src/main/java/co/lettermint/Webhook.java new file mode 100644 index 0000000..0b3670c --- /dev/null +++ b/src/main/java/co/lettermint/Webhook.java @@ -0,0 +1,363 @@ +package co.lettermint; + +import co.lettermint.exceptions.LettermintConfigException; +import co.lettermint.exceptions.WebhookVerificationException; +import co.lettermint.exceptions.WebhookVerificationException.Reason; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.time.Clock; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.regex.Pattern; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; + +/** + * Verifies Lettermint webhook deliveries: an HMAC-SHA256 signature over {@code "." + raw body} with + * the endpoint's signing secret ({@code whsec_...}, used as is), compared in constant time. + * Immutable and thread-safe. + * + *

{@code
+ * Webhook webhook = new Webhook(System.getenv("LETTERMINT_WEBHOOK_SECRET"));
+ * WebhookPayload event = webhook.verify(rawBody, headers);
+ * }
+ */ +public final class Webhook { + private static final String SIGNATURE_HEADER = "X-Lettermint-Signature"; + private static final String DELIVERY_HEADER = "X-Lettermint-Delivery"; + private static final Duration DEFAULT_TOLERANCE = Duration.ofSeconds(300); + private static final Pattern PRINTABLE_ASCII = Pattern.compile("^[\\x20-\\x7e]*$"); + private static final Pattern DIGITS = Pattern.compile("^[0-9]+$"); + private static final Pattern HEX_SHA256 = Pattern.compile("^[0-9a-fA-F]{64}$"); + /** Number.MAX_SAFE_INTEGER, as in the other SDKs. */ + private static final BigInteger MAX_SAFE_INTEGER = BigInteger.valueOf(9007199254740991L); + private static final TypeReference> OBJECT = new TypeReference<>() {}; + + private final SecretKeySpec key; + private final long tolerance; + private final Clock clock; + + /** + * Verifies with the default tolerance of 300 seconds. + * + * @param secret the webhook's signing secret, including its {@code whsec_} prefix + */ + public Webhook(String secret) { + this(secret, DEFAULT_TOLERANCE, Clock.systemUTC()); + } + + /** + * @param secret the webhook's signing secret, including its {@code whsec_} prefix + * @param tolerance the maximum difference between the signed timestamp and now, in either + * direction, in whole seconds; {@code Duration.ZERO} accepts only the current second + */ + public Webhook(String secret, Duration tolerance) { + this(secret, tolerance, Clock.systemUTC()); + } + + /** + * @param secret the webhook's signing secret, including its {@code whsec_} prefix + * @param tolerance the maximum difference between the signed timestamp and now, in whole seconds + * @param clock the clock to compare the timestamp with, for tests + */ + public Webhook(String secret, Duration tolerance, Clock clock) { + if (secret == null || secret.isEmpty()) { + throw new LettermintConfigException("The webhook signing secret must be a non-empty string."); + } + if (tolerance == null || tolerance.isNegative() || tolerance.getNano() != 0) { + throw new LettermintConfigException("tolerance must be a non-negative whole number of seconds."); + } + if (clock == null) { + throw new LettermintConfigException("clock must not be null."); + } + this.key = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); + this.tolerance = tolerance.getSeconds(); + this.clock = clock; + } + + /** + * @return the timestamp tolerance + */ + public Duration tolerance() { + return Duration.ofSeconds(tolerance); + } + + /** + * Verifies a delivery from its raw body and request headers, and returns the payload. Requires + * {@code X-Lettermint-Signature} and {@code X-Lettermint-Delivery} (which must equal the signed + * timestamp). Header names are case-insensitive; values may be strings or lists of strings, as in + * {@code Map}, {@code Map>}, Spring's {@code HttpHeaders} or + * JAX-RS {@code MultivaluedMap}. + * + * @param rawBody the raw request body, exactly as received + * @param headers the request headers + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + */ + public WebhookPayload verify(byte[] rawBody, Map headers) { + return verifyHeaders(rawBody, name -> mapLookup(headers, name)); + } + + /** + * @param rawBody the raw request body as a string (UTF-8 is signed) + * @param headers the request headers + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + * @see #verify(byte[], Map) + */ + public WebhookPayload verify(String rawBody, Map headers) { + return verifyHeaders(bytes(rawBody), name -> mapLookup(headers, name)); + } + + /** + * Verifies with a header lookup, for example {@code request::getHeader} of a servlet request. + * + * @param rawBody the raw request body, exactly as received + * @param header returns the value of a header (case-insensitive name), or null when it is missing + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + */ + public WebhookPayload verify(byte[] rawBody, Function header) { + return verifyHeaders(rawBody, name -> { + String value = header == null ? null : header.apply(name); + return value == null ? Lookup.MISSING : new Lookup(value, false, false); + }); + } + + private WebhookPayload verifyHeaders(byte[] rawBody, Function lookup) { + Lookup signature = lookup.apply(SIGNATURE_HEADER); + if (signature.missing) { + throw new WebhookVerificationException(Reason.SIGNATURE_HEADER_MISSING, "The X-Lettermint-Signature header is missing."); + } + if (signature.ambiguous) { + throw new WebhookVerificationException(Reason.SIGNATURE_HEADER_MALFORMED, "The request has more than one X-Lettermint-Signature header."); + } + Lookup delivery = lookup.apply(DELIVERY_HEADER); + if (delivery.missing) { + throw new WebhookVerificationException(Reason.DELIVERY_HEADER_MISSING, "The X-Lettermint-Delivery header is missing."); + } + if (delivery.ambiguous) { + throw new WebhookVerificationException(Reason.DELIVERY_TIMESTAMP_MISMATCH, "The request has more than one X-Lettermint-Delivery header."); + } + return verifySignature(rawBody, signature.value, delivery.value); + } + + /** + * @param rawBody the raw request body as a string + * @param header returns the value of a header, or null when it is missing + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + * @see #verify(byte[], Function) + */ + public WebhookPayload verify(String rawBody, Function header) { + return verify(bytes(rawBody), header); + } + + /** + * Verifies the raw body against an {@code X-Lettermint-Signature} value, for setups where the + * headers are not at hand. + * + * @param rawBody the raw request body + * @param signatureHeader the {@code X-Lettermint-Signature} value + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + */ + public WebhookPayload verifySignature(byte[] rawBody, String signatureHeader) { + return verifySignature(rawBody, signatureHeader, null); + } + + /** + * @param rawBody the raw request body as a string + * @param signatureHeader the {@code X-Lettermint-Signature} value + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + */ + public WebhookPayload verifySignature(String rawBody, String signatureHeader) { + return verifySignature(bytes(rawBody), signatureHeader, null); + } + + /** + * @param rawBody the raw request body as a string + * @param signatureHeader the {@code X-Lettermint-Signature} value + * @param deliveryHeader the {@code X-Lettermint-Delivery} value, which must equal the signed timestamp; or null + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + */ + public WebhookPayload verifySignature(String rawBody, String signatureHeader, String deliveryHeader) { + return verifySignature(bytes(rawBody), signatureHeader, deliveryHeader); + } + + /** + * Verifies the raw body against an {@code X-Lettermint-Signature} value. When {@code deliveryHeader} + * (the {@code X-Lettermint-Delivery} value) is given, it must equal the signed timestamp. + * + * @param rawBody the raw request body + * @param signatureHeader the {@code X-Lettermint-Signature} value + * @param deliveryHeader the {@code X-Lettermint-Delivery} value, or null + * @return the payload + * @throws WebhookVerificationException when the delivery is not genuine + */ + public WebhookPayload verifySignature(byte[] rawBody, String signatureHeader, String deliveryHeader) { + if (signatureHeader == null || signatureHeader.isBlank()) { + throw new WebhookVerificationException(Reason.SIGNATURE_HEADER_MISSING, "The X-Lettermint-Signature header is missing."); + } + Parsed parsed = parse(signatureHeader); + if (deliveryHeader != null && !deliveryHeader.trim().equals(parsed.timestamp)) { + throw new WebhookVerificationException(Reason.DELIVERY_TIMESTAMP_MISMATCH, "The X-Lettermint-Delivery header does not match the signed timestamp."); + } + if (rawBody == null || rawBody.length == 0) { + throw new WebhookVerificationException(Reason.BODY_INVALID, rawBody == null + ? "Pass the raw request body (a String or byte[]), not parsed JSON." + : "The raw request body is empty."); + } + long now = clock.instant().getEpochSecond(); + if (Math.abs(now - Long.parseLong(parsed.timestamp)) > tolerance) { + throw new WebhookVerificationException(Reason.TIMESTAMP_OUT_OF_TOLERANCE, "The signed timestamp is outside the allowed tolerance."); + } + byte[] expected = sign(parsed.timestamp, rawBody); + boolean matched = false; + for (byte[] candidate : parsed.signatures) { + matched |= MessageDigest.isEqual(candidate, expected); + } + if (!matched) { + throw new WebhookVerificationException(Reason.SIGNATURE_MISMATCH, "The webhook signature does not match."); + } + JsonNode tree; + try { + tree = Transport.MAPPER.readTree(rawBody); + } catch (IOException error) { + throw new WebhookVerificationException(Reason.PAYLOAD_INVALID, "The webhook payload is not valid JSON."); + } + if (tree == null || !tree.isObject()) { + throw new WebhookVerificationException(Reason.PAYLOAD_INVALID, "The webhook payload is not a JSON object."); + } + return new WebhookPayload(Transport.MAPPER.convertValue(tree, OBJECT)); + } + + private byte[] sign(String timestamp, byte[] body) { + try { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(key); + mac.update((timestamp + ".").getBytes(StandardCharsets.US_ASCII)); + return mac.doFinal(body); + } catch (GeneralSecurityException error) { + throw new IllegalStateException("HmacSHA256 is not available", error); + } + } + + private static byte[] bytes(String body) { + return body == null ? null : body.getBytes(StandardCharsets.UTF_8); + } + + // ------------------------------------------------------------ headers + private static final class Lookup { + static final Lookup MISSING = new Lookup(null, true, false); + static final Lookup AMBIGUOUS = new Lookup(null, false, true); + + final String value; + final boolean missing; + final boolean ambiguous; + + Lookup(String value, boolean missing, boolean ambiguous) { + this.value = value; + this.missing = missing; + this.ambiguous = ambiguous; + } + } + + private static Lookup mapLookup(Map headers, String name) { + if (headers == null) { + return Lookup.MISSING; + } + List values = new ArrayList<>(); + for (Map.Entry entry : headers.entrySet()) { + if (entry.getKey() == null || !entry.getKey().equalsIgnoreCase(name) || entry.getValue() == null) { + continue; + } + Object value = entry.getValue(); + if (value instanceof Collection collection) { + values.addAll(collection); + } else if (value instanceof Object[] array) { + values.addAll(Arrays.asList(array)); + } else { + values.add(value); + } + } + values.removeIf(Objects::isNull); + if (values.isEmpty()) { + return Lookup.MISSING; + } + if (values.size() > 1 || !(values.get(0) instanceof String)) { + return Lookup.AMBIGUOUS; + } + return new Lookup((String) values.get(0), false, false); + } + + // ------------------------------------------------------------ signature header + private record Parsed(String timestamp, List signatures) { + } + + private static WebhookVerificationException malformed(String detail) { + return new WebhookVerificationException(Reason.SIGNATURE_HEADER_MALFORMED, "The signature header is malformed: " + detail + "."); + } + + private static Parsed parse(String header) { + if (!PRINTABLE_ASCII.matcher(header).matches()) { + throw malformed("it contains non-ASCII or control characters"); + } + String timestamp = null; + List signatures = new ArrayList<>(); + for (String part : header.split(",", -1)) { + String entry = part.trim(); + int separator = entry.indexOf('='); + if (separator == -1) { + continue; + } + String name = entry.substring(0, separator); + String value = entry.substring(separator + 1); + if (name.equals("t")) { + if (timestamp != null) { + throw malformed("it has more than one timestamp"); + } + if (!DIGITS.matcher(value).matches() || new BigInteger(value).compareTo(MAX_SAFE_INTEGER) > 0) { + throw malformed("the timestamp is not a number of seconds"); + } + timestamp = value; + } else if (name.equals("v1") && HEX_SHA256.matcher(value).matches()) { + signatures.add(hex(value)); + } + } + if (timestamp == null) { + throw malformed("the timestamp (t=) is missing"); + } + if (signatures.isEmpty()) { + throw malformed("no v1 signature is present"); + } + return new Parsed(timestamp, signatures); + } + + private static byte[] hex(String value) { + byte[] bytes = new byte[value.length() / 2]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = (byte) Integer.parseInt(value.substring(i * 2, i * 2 + 2), 16); + } + return bytes; + } + + /** Contains no secret. */ + @Override + public String toString() { + return "Webhook{tolerance=" + tolerance + "s}"; + } +} diff --git a/src/main/java/co/lettermint/WebhookDeliveries.java b/src/main/java/co/lettermint/WebhookDeliveries.java new file mode 100644 index 0000000..f2fe705 --- /dev/null +++ b/src/main/java/co/lettermint/WebhookDeliveries.java @@ -0,0 +1,110 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.ListWebhookDeliveriesQuery; +import co.lettermint.types.Operations; +import co.lettermint.types.WebhookDeliveryData; +import co.lettermint.types.WebhookDeliveryListData; + +/** Delivery attempts of a webhook. Needs the team token. Thread-safe. */ +public final class WebhookDeliveries { + private final Transport transport; + + WebhookDeliveries(Transport transport) { + this.transport = transport; + } + + /** + * Lists the deliveries of a webhook, one page at a time. + * + * @param webhookId the webhook id + * @return the response + */ + public CursorPage list(String webhookId) { + return list(webhookId, null, null); + } + + /** + * Lists the deliveries of a webhook, one page at a time. + * + * @param webhookId the webhook id + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(String webhookId, ListWebhookDeliveriesQuery query) { + return list(webhookId, query, null); + } + + /** + * Lists the deliveries of a webhook, one page at a time. + * + * @param webhookId the webhook id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(String webhookId, ListWebhookDeliveriesQuery query, RequestOptions options) { + return transport.call(Operations.LIST_WEBHOOK_DELIVERIES, Transport.call("webhooks.deliveries.list").path(webhookId).query(query).options(options)); + } + + /** + * Iterates over every delivery of a webhook, following {@code next_cursor}. + * + * @param webhookId the webhook id + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(String webhookId) { + return iterate(webhookId, null, null); + } + + /** + * Iterates over every delivery of a webhook, following {@code next_cursor}. + * + * @param webhookId the webhook id + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(String webhookId, ListWebhookDeliveriesQuery query) { + return iterate(webhookId, query, null); + } + + /** + * Iterates over every delivery of a webhook, following {@code next_cursor}. + * + * @param webhookId the webhook id + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(String webhookId, ListWebhookDeliveriesQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_WEBHOOK_DELIVERIES, Transport.call("webhooks.deliveries.iterate").path(webhookId).query(query).options(options)); + } + + /** + * Retrieves one delivery attempt. + * + * @param webhookId the webhook id + * @param deliveryId the delivery id + * @return the response + */ + public WebhookDeliveryData retrieve(String webhookId, String deliveryId) { + return retrieve(webhookId, deliveryId, null); + } + + /** + * Retrieves one delivery attempt. + * + * @param webhookId the webhook id + * @param deliveryId the delivery id + * @param options per-call options, or null + * @return the response + */ + public WebhookDeliveryData retrieve(String webhookId, String deliveryId, RequestOptions options) { + return transport.call(Operations.GET_WEBHOOK_DELIVERY, Transport.call("webhooks.deliveries.retrieve").path(webhookId, deliveryId).options(options)); + } + + @Override + public String toString() { + return "WebhookDeliveries{}"; + } +} diff --git a/src/main/java/co/lettermint/WebhookPayload.java b/src/main/java/co/lettermint/WebhookPayload.java new file mode 100644 index 0000000..7f74e23 --- /dev/null +++ b/src/main/java/co/lettermint/WebhookPayload.java @@ -0,0 +1,81 @@ +package co.lettermint; + +import co.lettermint.types.WebhookEvent; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A verified webhook delivery. Unknown fields are kept in {@link #fields()}. + * + *
{@code
+ * WebhookPayload event = webhook.verify(rawBody, headers);
+ * if (WebhookEvent.MESSAGE_DELIVERED.equals(event.event())) {
+ *     String messageId = (String) event.data().get("message_id");
+ * }
+ * }
+ */ +public final class WebhookPayload { + private final Map fields; + + WebhookPayload(Map fields) { + this.fields = Collections.unmodifiableMap(new LinkedHashMap<>(fields)); + } + + /** + * @return the delivery id, or null + */ + public String id() { + return fields.get("id") instanceof String value ? value : null; + } + + /** + * @return the event, for example {@link WebhookEvent#MESSAGE_DELIVERED}; unknown events keep their + * raw name. Null when the payload has no string {@code event}. + */ + public WebhookEvent event() { + return fields.get("event") instanceof String value ? WebhookEvent.of(value) : null; + } + + /** + * @return when the event occurred (ISO 8601), from {@code timestamp} or else {@code created_at}; or null + */ + public String timestamp() { + if (fields.get("timestamp") instanceof String value) { + return value; + } + return fields.get("created_at") instanceof String value ? value : null; + } + + /** + * @return the event data (maps, lists and scalars as decoded by Jackson), or an empty map + */ + @SuppressWarnings("unchecked") + public Map data() { + Object data = fields.get("data"); + return data instanceof Map map ? Collections.unmodifiableMap((Map) map) : Map.of(); + } + + /** + * Converts the event data into your own type with Jackson, for example a record. + * + * @param type the target type + * @param the target type + * @return the converted data + */ + public T data(Class type) { + return Transport.MAPPER.convertValue(data(), type); + } + + /** + * @return every top-level field of the payload + */ + public Map fields() { + return fields; + } + + @Override + public String toString() { + return "WebhookPayload{id=" + id() + ", event=" + event() + ", timestamp=" + timestamp() + "}"; + } +} diff --git a/src/main/java/co/lettermint/Webhooks.java b/src/main/java/co/lettermint/Webhooks.java new file mode 100644 index 0000000..2b4f504 --- /dev/null +++ b/src/main/java/co/lettermint/Webhooks.java @@ -0,0 +1,224 @@ +package co.lettermint; + +import co.lettermint.types.CursorPage; +import co.lettermint.types.ListWebhooksQuery; +import co.lettermint.types.MessageResponse; +import co.lettermint.types.Operations; +import co.lettermint.types.StoreWebhookData; +import co.lettermint.types.TestWebhookResponse; +import co.lettermint.types.UpdateWebhookData; +import co.lettermint.types.WebhookData; +import co.lettermint.types.WebhookListData; +import co.lettermint.types.WebhookMutationResponse; +import co.lettermint.types.WebhookSecretResponse; + +/** Webhook endpoints. Needs the team token. To verify incoming deliveries, use {@link Webhook}. Thread-safe. */ +public final class Webhooks { + private final Transport transport; + private final WebhookDeliveries deliveries; + + Webhooks(Transport transport) { + this.transport = transport; + this.deliveries = new WebhookDeliveries(transport); + } + + /** + * @return delivery attempts of a webhook + */ + public WebhookDeliveries deliveries() { + return deliveries; + } + + /** + * Lists webhooks, one page at a time. + * + * @return the response + */ + public CursorPage list() { + return list(null, null); + } + + /** + * Lists webhooks, one page at a time. + * + * @param query the query parameters, or null + * @return the response + */ + public CursorPage list(ListWebhooksQuery query) { + return list(query, null); + } + + /** + * Lists webhooks, one page at a time. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return the response + */ + public CursorPage list(ListWebhooksQuery query, RequestOptions options) { + return transport.call(Operations.LIST_WEBHOOKS, Transport.call("webhooks.list").query(query).options(options)); + } + + /** + * Iterates over every webhook, following {@code next_cursor}. + * + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate() { + return iterate(null, null); + } + + /** + * Iterates over every webhook, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListWebhooksQuery query) { + return iterate(query, null); + } + + /** + * Iterates over every webhook, following {@code next_cursor}. + * + * @param query the query parameters, or null + * @param options per-call options, or null + * @return every item, fetched page by page as you iterate + */ + public CursorIterable iterate(ListWebhooksQuery query, RequestOptions options) { + return transport.paginate(Operations.LIST_WEBHOOKS, Transport.call("webhooks.iterate").query(query).options(options)); + } + + /** + * Creates a webhook. The response holds its signing secret once. + * + * @param body the request body + * @return the response + */ + public WebhookSecretResponse create(StoreWebhookData body) { + return create(body, null); + } + + /** + * Creates a webhook. The response holds its signing secret once. + * + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public WebhookSecretResponse create(StoreWebhookData body, RequestOptions options) { + return transport.call(Operations.CREATE_WEBHOOK, Transport.call("webhooks.create").body(body).options(options)); + } + + /** + * Retrieves a webhook. + * + * @param webhookId the webhook id + * @return the response + */ + public WebhookData retrieve(String webhookId) { + return retrieve(webhookId, null); + } + + /** + * Retrieves a webhook. + * + * @param webhookId the webhook id + * @param options per-call options, or null + * @return the response + */ + public WebhookData retrieve(String webhookId, RequestOptions options) { + return transport.call(Operations.GET_WEBHOOK, Transport.call("webhooks.retrieve").path(webhookId).options(options)); + } + + /** + * Updates a webhook. + * + * @param webhookId the webhook id + * @param body the request body + * @return the response + */ + public WebhookMutationResponse update(String webhookId, UpdateWebhookData body) { + return update(webhookId, body, null); + } + + /** + * Updates a webhook. + * + * @param webhookId the webhook id + * @param body the request body + * @param options per-call options, or null + * @return the response + */ + public WebhookMutationResponse update(String webhookId, UpdateWebhookData body, RequestOptions options) { + return transport.call(Operations.UPDATE_WEBHOOK, Transport.call("webhooks.update").path(webhookId).body(body).options(options)); + } + + /** + * Deletes a webhook. + * + * @param webhookId the webhook id + * @return the response + */ + public MessageResponse delete(String webhookId) { + return delete(webhookId, null); + } + + /** + * Deletes a webhook. + * + * @param webhookId the webhook id + * @param options per-call options, or null + * @return the response + */ + public MessageResponse delete(String webhookId, RequestOptions options) { + return transport.call(Operations.DELETE_WEBHOOK, Transport.call("webhooks.delete").path(webhookId).options(options)); + } + + /** + * Sends a {@code webhook.test} delivery. + * + * @param webhookId the webhook id + * @return the response + */ + public TestWebhookResponse test(String webhookId) { + return test(webhookId, null); + } + + /** + * Sends a {@code webhook.test} delivery. + * + * @param webhookId the webhook id + * @param options per-call options, or null + * @return the response + */ + public TestWebhookResponse test(String webhookId, RequestOptions options) { + return transport.call(Operations.TEST_WEBHOOK, Transport.call("webhooks.test").path(webhookId).options(options)); + } + + /** + * Replaces the signing secret. The response holds the new secret once. + * + * @param webhookId the webhook id + * @return the response + */ + public WebhookSecretResponse regenerateSecret(String webhookId) { + return regenerateSecret(webhookId, null); + } + + /** + * Replaces the signing secret. The response holds the new secret once. + * + * @param webhookId the webhook id + * @param options per-call options, or null + * @return the response + */ + public WebhookSecretResponse regenerateSecret(String webhookId, RequestOptions options) { + return transport.call(Operations.REGENERATE_WEBHOOK_SECRET, Transport.call("webhooks.regenerateSecret").path(webhookId).options(options)); + } + + @Override + public String toString() { + return "Webhooks{}"; + } +} diff --git a/src/main/java/co/lettermint/api/ApiClient.java b/src/main/java/co/lettermint/api/ApiClient.java deleted file mode 100644 index 4c8bb48..0000000 --- a/src/main/java/co/lettermint/api/ApiClient.java +++ /dev/null @@ -1,409 +0,0 @@ -package co.lettermint.api; - -import co.lettermint.client.LettermintClient; -import co.lettermint.models.api.*; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.util.Map; - -public class ApiClient { - private final LettermintClient client; - private final DomainsEndpoint domains; - private final MessagesEndpoint messages; - private final ProjectsEndpoint projects; - private final RoutesEndpoint routes; - private final StatsEndpoint stats; - private final SuppressionsEndpoint suppressions; - private final TeamEndpoint team; - private final WebhooksEndpoint webhooks; - - public ApiClient(String apiToken, String baseUrl) { - this.client = new LettermintClient(apiToken, baseUrl, LettermintClient.AuthMode.BEARER); - this.domains = new DomainsEndpoint(client); - this.messages = new MessagesEndpoint(client); - this.projects = new ProjectsEndpoint(client); - this.routes = new RoutesEndpoint(client); - this.stats = new StatsEndpoint(client); - this.suppressions = new SuppressionsEndpoint(client); - this.team = new TeamEndpoint(client); - this.webhooks = new WebhooksEndpoint(client); - } - - public String ping() { - return client.getRaw("/ping").trim(); - } - - public BlockedFileTypesResponse blockedFileTypes() { - return client.get("/blocked-file-types", BlockedFileTypesResponse.class); - } - - public AnalyticsResponse analytics(AnalyticsRequest payload) { - return client.post("/analytics", payload, AnalyticsResponse.class); - } - - public DomainsEndpoint domains() { - return domains; - } - - public MessagesEndpoint messages() { - return messages; - } - - public ProjectsEndpoint projects() { - return projects; - } - - public RoutesEndpoint routes() { - return routes; - } - - public StatsEndpoint stats() { - return stats; - } - - public SuppressionsEndpoint suppressions() { - return suppressions; - } - - public TeamEndpoint team() { - return team; - } - - public WebhooksEndpoint webhooks() { - return webhooks; - } - - private static String segment(String value) { - try { - return URLEncoder.encode(value, "UTF-8").replace("+", "%20"); - } catch (UnsupportedEncodingException e) { - throw new IllegalStateException(e); - } - } - - public static class DomainsEndpoint { - private final LettermintClient client; - - DomainsEndpoint(LettermintClient client) { - this.client = client; - } - - public DomainIndexResponse list() { - return list(null); - } - - public DomainIndexResponse list(Map query) { - return client.get("/domains", DomainIndexResponse.class, query); - } - - public DomainData create(StoreDomainData payload) { - return client.post("/domains", payload, DomainData.class); - } - - public DomainData retrieve(String domainId) { - return client.get("/domains/" + segment(domainId), DomainData.class); - } - - public DomainDestroyResponse delete(String domainId) { - return client.delete("/domains/" + segment(domainId), DomainDestroyResponse.class); - } - - public DomainVerifyDnsRecordsResponse verifyDnsRecords(String domainId) { - return client.post("/domains/" + segment(domainId) + "/dns-records/verify", null, DomainVerifyDnsRecordsResponse.class); - } - - public DomainVerifySpecificDnsRecordResponse verifyDnsRecord(String domainId, String recordId) { - return client.post("/domains/" + segment(domainId) + "/dns-records/" + segment(recordId) + "/verify", null, DomainVerifySpecificDnsRecordResponse.class); - } - - public DomainUpdateProjectsResponse updateProjects(String domainId, UpdateDomainProjectsData payload) { - return client.put("/domains/" + segment(domainId) + "/projects", payload, DomainUpdateProjectsResponse.class); - } - } - - // Keep the pre-v2.6 JVM descriptor through javac's covariant return bridge. - private interface ScheduledMessageCancellation { - RescheduleMessageResponse cancel(String messageId); - } - - public static class MessagesEndpoint implements ScheduledMessageCancellation { - private final LettermintClient client; - - MessagesEndpoint(LettermintClient client) { - this.client = client; - } - - public MessageIndexResponse list() { - return list(null); - } - - public MessageIndexResponse list(Map query) { - return client.get("/messages", MessageIndexResponse.class, query); - } - - public MessageData retrieve(String messageId) { - return client.get("/messages/" + segment(messageId), MessageData.class); - } - - public RescheduleMessageResponse reschedule(String messageId, RescheduleMessageRequest payload) { - return client.patch("/messages/" + segment(messageId), payload, RescheduleMessageResponse.class); - } - - @Override - public CancelScheduledMessageResponse cancel(String messageId) { - return client.post("/messages/" + segment(messageId) + "/cancel", null, CancelScheduledMessageResponse.class); - } - - public ProcessInboundMessageResponse process(String messageId) { - return client.post("/messages/" + segment(messageId) + "/process", null, ProcessInboundMessageResponse.class); - } - - public MessageEventsResponse events(String messageId) { - return events(messageId, null); - } - - public MessageEventsResponse events(String messageId, Map query) { - return client.get("/messages/" + segment(messageId) + "/events", MessageEventsResponse.class, query); - } - - public String source(String messageId) { - return client.getRaw("/messages/" + segment(messageId) + "/source"); - } - - public String html(String messageId) { - return client.getRaw("/messages/" + segment(messageId) + "/html"); - } - - public String text(String messageId) { - return client.getRaw("/messages/" + segment(messageId) + "/text"); - } - } - - public static class ProjectsEndpoint { - public GetReportForwardingResponse retrieveReportForwarding(String projectId) { - return client.get("/projects/" + segment(projectId) + "/report-forwarding", GetReportForwardingResponse.class); - } - - public UpdateReportForwardingResponse updateReportForwarding(String projectId, ReportForwardingRequest payload) { - return client.put("/projects/" + segment(projectId) + "/report-forwarding", payload, UpdateReportForwardingResponse.class); - } - - public void deleteReportForwarding(String projectId) { - client.delete("/projects/" + segment(projectId) + "/report-forwarding", Void.class); - } - - public VerifyReportForwardingResponse verifyReportForwarding(String projectId, VerifyReportForwardingRequest payload) { - return client.post("/projects/" + segment(projectId) + "/report-forwarding/verify", payload, VerifyReportForwardingResponse.class); - } - - public ResendReportForwardingCodeResponse resendReportForwardingCode(String projectId) { - return client.post("/projects/" + segment(projectId) + "/report-forwarding/resend-code", null, ResendReportForwardingCodeResponse.class); - } - private final LettermintClient client; - - ProjectsEndpoint(LettermintClient client) { - this.client = client; - } - - public ProjectIndexResponse list() { - return list(null); - } - - public ProjectIndexResponse list(Map query) { - return client.get("/projects", ProjectIndexResponse.class, query); - } - - public ProjectStoreResponse create(StoreProjectData payload) { - return client.post("/projects", payload, ProjectStoreResponse.class); - } - - public ProjectData retrieve(String projectId) { - return client.get("/projects/" + segment(projectId), ProjectData.class); - } - - public ProjectUpdateResponse update(String projectId, UpdateProjectData payload) { - return client.put("/projects/" + segment(projectId), payload, ProjectUpdateResponse.class); - } - - public ProjectDestroyResponse delete(String projectId) { - return client.delete("/projects/" + segment(projectId), ProjectDestroyResponse.class); - } - - public ProjectRotateTokenResponse rotateToken(String projectId) { - return client.post("/projects/" + segment(projectId) + "/rotate-token", null, ProjectRotateTokenResponse.class); - } - - public RouteIndexResponse routes(String projectId) { - return routes(projectId, null); - } - - public RouteIndexResponse routes(String projectId, Map query) { - return client.get("/projects/" + segment(projectId) + "/routes", RouteIndexResponse.class, query); - } - - public RouteStoreResponse createRoute(String projectId, StoreRouteData payload) { - return client.post("/projects/" + segment(projectId) + "/routes", payload, RouteStoreResponse.class); - } - } - - public static class RoutesEndpoint { - private final LettermintClient client; - - RoutesEndpoint(LettermintClient client) { - this.client = client; - } - - public RouteData retrieve(String routeId) { - return client.get("/routes/" + segment(routeId), RouteData.class); - } - - public RouteUpdateResponse update(String routeId, UpdateRouteData payload) { - return client.put("/routes/" + segment(routeId), payload, RouteUpdateResponse.class); - } - - public RouteDestroyResponse delete(String routeId) { - return client.delete("/routes/" + segment(routeId), RouteDestroyResponse.class); - } - - public RouteVerifyInboundDomainResponse verifyInboundDomain(String routeId) { - return client.post("/routes/" + segment(routeId) + "/verify-inbound-domain", null, RouteVerifyInboundDomainResponse.class); - } - } - - public static class StatsEndpoint { - private final LettermintClient client; - - StatsEndpoint(LettermintClient client) { - this.client = client; - } - - public StatsData retrieve() { - return retrieve(null); - } - - public StatsData retrieve(Map query) { - return client.get("/stats", StatsData.class, query); - } - } - - public static class SuppressionsEndpoint { - private final LettermintClient client; - - SuppressionsEndpoint(LettermintClient client) { - this.client = client; - } - - public SuppressionIndexResponse list() { - return list(null); - } - - public SuppressionIndexResponse list(Map query) { - return client.get("/suppressions", SuppressionIndexResponse.class, query); - } - - public SuppressionStoreResponse create(StoreSuppressionData payload) { - return client.post("/suppressions", payload, SuppressionStoreResponse.class); - } - - public SuppressionDestroyResponse delete(String suppressionId) { - return client.delete("/suppressions/" + segment(suppressionId), SuppressionDestroyResponse.class); - } - } - - public static class TeamEndpoint { - private final LettermintClient client; - - TeamEndpoint(LettermintClient client) { - this.client = client; - } - - public TeamData retrieve() { - return client.get("/team", TeamData.class); - } - - public TeamUpdateResponse update(UpdateTeamData payload) { - return client.put("/team", payload, TeamUpdateResponse.class); - } - - public TeamUsageDetailData usage() { - return usage(null); - } - - public TeamUsageDetailData usage(Map query) { - return client.get("/team/usage", TeamUsageDetailData.class, query); - } - - public TeamRolesResponse roles() { - return client.get("/team/roles", TeamRolesResponse.class); - } - - public TeamMembersResponse members() { - return members(null); - } - - public TeamMembersResponse members(Map query) { - return client.get("/team/members", TeamMembersResponse.class, query); - } - - public TeamMemberData member(String userId) { - return client.get("/team/members/" + segment(userId), TeamMemberData.class); - } - - public TeamMemberData updateMemberAssignment(String userId, UpdateTeamMemberAssignmentData payload) { - return client.put("/team/members/" + segment(userId) + "/assignment", payload, TeamMemberData.class); - } - } - - public static class WebhooksEndpoint { - private final LettermintClient client; - - WebhooksEndpoint(LettermintClient client) { - this.client = client; - } - - public WebhookIndexResponse list() { - return list(null); - } - - public WebhookIndexResponse list(Map query) { - return client.get("/webhooks", WebhookIndexResponse.class, query); - } - - public WebhookStoreResponse create(StoreWebhookData payload) { - return client.post("/webhooks", payload, WebhookStoreResponse.class); - } - - public WebhookData retrieve(String webhookId) { - return client.get("/webhooks/" + segment(webhookId), WebhookData.class); - } - - public WebhookUpdateResponse update(String webhookId, UpdateWebhookData payload) { - return client.put("/webhooks/" + segment(webhookId), payload, WebhookUpdateResponse.class); - } - - public WebhookDestroyResponse delete(String webhookId) { - return client.delete("/webhooks/" + segment(webhookId), WebhookDestroyResponse.class); - } - - public WebhookTestResponse test(String webhookId) { - return client.post("/webhooks/" + segment(webhookId) + "/test", null, WebhookTestResponse.class); - } - - public WebhookRegenerateSecretResponse regenerateSecret(String webhookId) { - return client.post("/webhooks/" + segment(webhookId) + "/regenerate-secret", null, WebhookRegenerateSecretResponse.class); - } - - public WebhookDeliveriesResponse deliveries(String webhookId) { - return deliveries(webhookId, null); - } - - public WebhookDeliveriesResponse deliveries(String webhookId, Map query) { - return client.get("/webhooks/" + segment(webhookId) + "/deliveries", WebhookDeliveriesResponse.class, query); - } - - public WebhookDeliveryData delivery(String webhookId, String deliveryId) { - return client.get("/webhooks/" + segment(webhookId) + "/deliveries/" + segment(deliveryId), WebhookDeliveryData.class); - } - } -} diff --git a/src/main/java/co/lettermint/client/LettermintClient.java b/src/main/java/co/lettermint/client/LettermintClient.java deleted file mode 100644 index 821207c..0000000 --- a/src/main/java/co/lettermint/client/LettermintClient.java +++ /dev/null @@ -1,260 +0,0 @@ -package co.lettermint.client; - -import co.lettermint.BuildInfo; -import co.lettermint.exceptions.HttpRequestException; -import co.lettermint.exceptions.LettermintException; -import co.lettermint.exceptions.ValidationException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.*; - -import java.io.IOException; -import java.net.SocketTimeoutException; -import java.net.URLEncoder; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * HTTP client for Lettermint API requests. - */ -public class LettermintClient { - - private static final String DEFAULT_BASE_URL = "https://api.lettermint.co/v1"; - private static final int DEFAULT_TIMEOUT_SECONDS = 30; - - private static final MediaType JSON = MediaType.get("application/json; charset=utf-8"); - - private final String apiToken; - private final String baseUrl; - private final AuthMode authMode; - private final OkHttpClient httpClient; - private final ObjectMapper objectMapper; - - public LettermintClient(String apiToken) { - this(apiToken, DEFAULT_BASE_URL); - } - - public LettermintClient(String apiToken, String baseUrl) { - this(apiToken, baseUrl, AuthMode.SENDING); - } - - public LettermintClient(String apiToken, String baseUrl, AuthMode authMode) { - if (apiToken == null || apiToken.isEmpty()) { - throw new IllegalArgumentException("API token is required"); - } - - this.apiToken = apiToken; - this.baseUrl = baseUrl != null ? baseUrl : DEFAULT_BASE_URL; - this.authMode = authMode; - this.objectMapper = new ObjectMapper(); - this.httpClient = buildHttpClient(); - } - - private OkHttpClient buildHttpClient() { - return new OkHttpClient.Builder() - .connectTimeout(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .readTimeout(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .writeTimeout(DEFAULT_TIMEOUT_SECONDS, TimeUnit.SECONDS) - .addInterceptor(this::addDefaultHeaders) - .build(); - } - - private Response addDefaultHeaders(Interceptor.Chain chain) throws IOException { - Request original = chain.request(); - Request.Builder builder = original.newBuilder() - .header("Content-Type", "application/json") - .header("Accept", "application/json") - .header("User-Agent", buildUserAgent()); - - if (authMode == AuthMode.BEARER) { - builder.header("Authorization", "Bearer " + apiToken); - builder.removeHeader("x-lettermint-token"); - } else { - builder.header("x-lettermint-token", apiToken); - builder.removeHeader("Authorization"); - } - - return chain.proceed(builder.build()); - } - - private String buildUserAgent() { - String javaVersion = System.getProperty("java.version", "unknown"); - return String.format("Lettermint/%s (Java; Java %s)", BuildInfo.VERSION, javaVersion); - } - - public T post(String path, Object payload, Class responseClass) { - return post(path, payload, responseClass, null); - } - - public T post(String path, Object payload, Class responseClass, Map headers) { - return request("POST", url(path, null), payload, responseClass, null, headers); - } - - public T post(String path, Object payload, TypeReference responseType) { - return post(path, payload, responseType, null); - } - - public T post(String path, Object payload, TypeReference responseType, Map headers) { - return request("POST", url(path, null), payload, null, responseType, headers); - } - - public T get(String path, Class responseClass) { - return get(path, responseClass, null); - } - - public T get(String path, Class responseClass, Map query) { - return request("GET", url(path, query), null, responseClass, null, null); - } - - public T put(String path, Object payload, Class responseClass) { - return request("PUT", url(path, null), payload, responseClass, null, null); - } - - public T patch(String path, Object payload, Class responseClass) { - return request("PATCH", url(path, null), payload, responseClass, null, null); - } - - public T delete(String path, Class responseClass) { - return request("DELETE", url(path, null), null, responseClass, null, null); - } - - public String getRaw(String path) { - Request request = new Request.Builder().url(url(path, null)).get().build(); - try (Response response = httpClient.newCall(request).execute()) { - String responseBody = response.body() != null ? response.body().string() : ""; - - if (!response.isSuccessful()) { - handleErrorResponse(response.code(), responseBody); - } - - return responseBody; - } catch (SocketTimeoutException e) { - throw new LettermintException("Request timed out", e); - } catch (IOException e) { - throw new LettermintException("Request failed: " + e.getMessage(), e); - } - } - - private T request(String method, String requestUrl, Object payload, Class responseClass, TypeReference responseType, Map headers) { - Request.Builder requestBuilder = new Request.Builder().url(requestUrl); - RequestBody body = null; - - if (payload != null) { - try { - body = RequestBody.create(objectMapper.writeValueAsString(payload), JSON); - } catch (JsonProcessingException e) { - throw new LettermintException("Failed to serialize request body", e); - } - } - - if ("POST".equals(method)) { - requestBuilder.post(body != null ? body : RequestBody.create(new byte[0], JSON)); - } else if ("PUT".equals(method)) { - requestBuilder.put(body != null ? body : RequestBody.create(new byte[0], JSON)); - } else if ("PATCH".equals(method)) { - requestBuilder.patch(body != null ? body : RequestBody.create(new byte[0], JSON)); - } else if ("DELETE".equals(method)) { - requestBuilder.delete(); - } else { - requestBuilder.get(); - } - - if (headers != null) { - for (Map.Entry entry : headers.entrySet()) { - requestBuilder.header(entry.getKey(), entry.getValue()); - } - } - - Request request = requestBuilder.build(); - - try (Response response = httpClient.newCall(request).execute()) { - String responseBody = response.body() != null ? response.body().string() : ""; - - if (!response.isSuccessful()) { - handleErrorResponse(response.code(), responseBody); - } - - if (responseClass != null) { - if (response.code() == 204 && responseClass == Void.class) { - return null; - } - return objectMapper.readValue(responseBody, responseClass); - } - return objectMapper.readValue(responseBody, responseType); - } catch (SocketTimeoutException e) { - throw new LettermintException("Request timed out", e); - } catch (IOException e) { - throw new LettermintException("Request failed: " + e.getMessage(), e); - } - } - - private String url(String path) { - return url(path, null); - } - - private String url(String path, Map query) { - if (isAbsolutePath(path)) { - throw new IllegalArgumentException("Request path must be relative"); - } - - StringBuilder result = new StringBuilder(baseUrl.replaceAll("/+$", "") + path); - if (query != null && !query.isEmpty()) { - result.append("?"); - boolean first = true; - for (Map.Entry entry : query.entrySet()) { - if (!first) { - result.append("&"); - } - first = false; - result.append(encode(entry.getKey())).append("=").append(encode(entry.getValue())); - } - } - return result.toString(); - } - - private boolean isAbsolutePath(String path) { - return path.matches("^[a-zA-Z][a-zA-Z0-9+.-]*:.*") || path.startsWith("//"); - } - - private String encode(String value) { - try { - return URLEncoder.encode(value, "UTF-8"); - } catch (IOException e) { - throw new LettermintException("Failed to encode query parameter", e); - } - } - - private void handleErrorResponse(int statusCode, String responseBody) { - String message = extractErrorMessage(responseBody, statusCode); - - if (statusCode == 422) { - throw new ValidationException(message, responseBody); - } - - throw new HttpRequestException(message, statusCode, responseBody); - } - - private String extractErrorMessage(String responseBody, int statusCode) { - try { - Map errorMap = objectMapper.readValue(responseBody, Map.class); - if (errorMap.containsKey("message")) { - return (String) errorMap.get("message"); - } - if (errorMap.containsKey("error")) { - return (String) errorMap.get("error"); - } - } catch (Exception ignored) { - } - return "HTTP " + statusCode + " error"; - } - - public ObjectMapper getObjectMapper() { - return objectMapper; - } - - public enum AuthMode { - SENDING, - BEARER - } -} diff --git a/src/main/java/co/lettermint/endpoints/EmailEndpoint.java b/src/main/java/co/lettermint/endpoints/EmailEndpoint.java deleted file mode 100644 index 96936cd..0000000 --- a/src/main/java/co/lettermint/endpoints/EmailEndpoint.java +++ /dev/null @@ -1,388 +0,0 @@ -package co.lettermint.endpoints; - -import co.lettermint.client.LettermintClient; -import co.lettermint.models.Attachment; -import co.lettermint.models.SendEmailResponse; -import co.lettermint.models.MessageTag; -import co.lettermint.models.api.SendMailRequest; -import co.lettermint.models.api.SendMailResponse; -import com.fasterxml.jackson.core.type.TypeReference; - -import java.util.*; - -/** - * Fluent builder for sending emails via the Lettermint API. - */ -public class EmailEndpoint extends Endpoint { - - private String from; - private List to; - private List cc; - private List bcc; - private List replyTo; - private String subject; - private String scheduledAt; - private String html; - private String text; - private Map headers; - private List attachments; - private String route; - private Map metadata; - private String tag; - private List tags; - private Map settings; - private String sandboxResult; - private String idempotencyKey; - - public EmailEndpoint(LettermintClient client) { - super(client); - reset(); - } - - /** - * Reset all fields to initial state. - */ - private void reset() { - this.from = null; - this.to = new ArrayList<>(); - this.cc = new ArrayList<>(); - this.bcc = new ArrayList<>(); - this.replyTo = new ArrayList<>(); - this.subject = null; - this.scheduledAt = null; - this.html = null; - this.text = null; - this.headers = new LinkedHashMap<>(); - this.attachments = new ArrayList<>(); - this.route = null; - this.metadata = new LinkedHashMap<>(); - this.tag = null; - this.tags = new ArrayList<>(); - this.settings = null; - this.sandboxResult = null; - this.idempotencyKey = null; - } - - /** - * Set the sender email address. - * Format: {@code "Name "} or just {@code "email"} - */ - public EmailEndpoint from(String from) { - this.from = from; - return this; - } - - /** - * Set recipient email addresses. Replaces any existing recipients. - */ - public EmailEndpoint to(String... emails) { - this.to = new ArrayList<>(Arrays.asList(emails)); - return this; - } - - /** - * Set CC email addresses. Replaces any existing CC recipients. - */ - public EmailEndpoint cc(String... emails) { - this.cc = new ArrayList<>(Arrays.asList(emails)); - return this; - } - - /** - * Set BCC email addresses. Replaces any existing BCC recipients. - */ - public EmailEndpoint bcc(String... emails) { - this.bcc = new ArrayList<>(Arrays.asList(emails)); - return this; - } - - /** - * Set reply-to email addresses. Replaces any existing reply-to addresses. - */ - public EmailEndpoint replyTo(String... emails) { - this.replyTo = new ArrayList<>(Arrays.asList(emails)); - return this; - } - - /** - * Set the email subject. - */ - public EmailEndpoint subject(String subject) { - this.subject = subject; - return this; - } - - /** Set the requested delivery time for the email. */ - public EmailEndpoint scheduledAt(String scheduledAt) { - this.scheduledAt = scheduledAt; - return this; - } - - /** - * Set the HTML content of the email. - */ - public EmailEndpoint html(String html) { - this.html = html; - return this; - } - - /** - * Set the plain text content of the email. - */ - public EmailEndpoint text(String text) { - this.text = text; - return this; - } - - /** - * Set custom email headers. - */ - public EmailEndpoint headers(Map headers) { - this.headers = new LinkedHashMap<>(headers); - return this; - } - - /** - * Add a single custom header. - */ - public EmailEndpoint header(String name, String value) { - this.headers.put(name, value); - return this; - } - - /** - * Attach a file to the email. - * - * @param filename The filename to use for the attachment - * @param content Base64-encoded file content - */ - public EmailEndpoint attach(String filename, String content) { - this.attachments.add(new Attachment(filename, content)); - return this; - } - - /** - * Attach an inline file to the email. - * - * @param filename The filename to use for the attachment - * @param content Base64-encoded file content - * @param contentId Content-ID for inline attachments (e.g., for embedding images) - */ - public EmailEndpoint attach(String filename, String content, String contentId) { - this.attachments.add(new Attachment(filename, content, contentId, null)); - return this; - } - - /** - * Attach an inline file to the email and specify the {@code Content-Type} - * - * @param filename The filename to use for the attachment - * @param content Base64-encoded file content - * @param contentId Content-ID for inline attachments (e.g., for embedding images) - * @param contentType MIME type of the attachment (e.g., "image/png") - */ - public EmailEndpoint attach(String filename, String content, String contentId, String contentType) { - this.attachments.add(new Attachment(filename, content, contentId, contentType)); - return this; - } - - /** - * Set the route slug for sending through a specific route. - */ - public EmailEndpoint route(String route) { - this.route = route; - return this; - } - - /** - * Set metadata to attach to the email. - */ - public EmailEndpoint metadata(Map metadata) { - this.metadata = new LinkedHashMap<>(metadata); - return this; - } - - /** - * Add a single metadata key-value pair. - */ - public EmailEndpoint metadata(String key, Object value) { - this.metadata.put(key, value); - return this; - } - - /** - * Set the email tag. - */ - public EmailEndpoint tag(String tag) { - if (tag != null && tags.size() >= 20) { - throw new IllegalArgumentException("A legacy tag and no more than 19 message tags are permitted"); - } - this.tag = tag; - return this; - } - - /** - * Set reusable name-value tags for the email. - */ - @SafeVarargs - public final EmailEndpoint tags(Map... tags) { - MessageTag[] normalized = new MessageTag[tags.length]; - for (int index = 0; index < tags.length; index++) { - normalized[index] = new MessageTag(tags[index].get("name"), tags[index].get("value")); - } - return tags(normalized); - } - - /** - * Set typed reusable name-value tags for the email. - */ - public final EmailEndpoint tags(MessageTag... tags) { - int maximum = tag == null ? 20 : 19; - if (tags.length > maximum) { - throw new IllegalArgumentException("No more than " + maximum + " message tags are permitted"); - } - Set names = new HashSet<>(); - for (MessageTag messageTag : tags) { - if (!names.add(messageTag.getName())) { - throw new IllegalArgumentException("Message tag names must be unique and case-sensitive"); - } - } - this.tags = new ArrayList<>(Arrays.asList(tags)); - return this; - } - - /** - * Set per-email settings that override the selected route. - */ - public EmailEndpoint settings(Map settings) { - this.settings = new LinkedHashMap<>(settings); - return this; - } - - /** - * Select the simulated result for a Sandbox project message. - */ - public EmailEndpoint sandboxResult(String sandboxResult) { - this.sandboxResult = sandboxResult; - return this; - } - - /** - * Set an idempotency key for the request. - */ - public EmailEndpoint idempotencyKey(String key) { - this.idempotencyKey = key; - return this; - } - - /** - * Send the email and return the response. - * Clears all fields after sending (matches PHP SDK behavior). - */ - public SendEmailResponse send() { - Map payload = buildPayload(); - Map requestHeaders = null; - - if (idempotencyKey != null && !idempotencyKey.isEmpty()) { - requestHeaders = Collections.singletonMap("Idempotency-Key", idempotencyKey); - } - - try { - return client.post("/send", payload, SendEmailResponse.class, requestHeaders); - } finally { - reset(); - } - } - - public List sendBatch(List payloads) { - Map requestHeaders = null; - - if (idempotencyKey != null && !idempotencyKey.isEmpty()) { - requestHeaders = Collections.singletonMap("Idempotency-Key", idempotencyKey); - } - - try { - return client.post("/send/batch", payloads, new TypeReference>() {}, requestHeaders); - } finally { - reset(); - } - } - - public String ping() { - return client.getRaw("/ping").trim(); - } - - private Map buildPayload() { - Map payload = new LinkedHashMap<>(); - - if (from != null) { - payload.put("from", from); - } - - if (!to.isEmpty()) { - payload.put("to", to); - } - - if (!cc.isEmpty()) { - payload.put("cc", cc); - } - - if (!bcc.isEmpty()) { - payload.put("bcc", bcc); - } - - if (!replyTo.isEmpty()) { - payload.put("reply_to", replyTo); - } - - if (subject != null) { - payload.put("subject", subject); - } - - if (scheduledAt != null) { - payload.put("scheduled_at", scheduledAt); - } - - if (html != null) { - payload.put("html", html); - } - - if (text != null) { - payload.put("text", text); - } - - if (!headers.isEmpty()) { - payload.put("headers", headers); - } - - if (!attachments.isEmpty()) { - payload.put("attachments", attachments); - } - - if (route != null) { - payload.put("route", route); - } - - if (!metadata.isEmpty()) { - payload.put("metadata", metadata); - } - - if (tag != null) { - payload.put("tag", tag); - } - - if (!tags.isEmpty()) { - payload.put("tags", tags); - } - - if (settings != null) { - payload.put("settings", settings); - } - - if (sandboxResult != null) { - payload.put("sandbox_result", sandboxResult); - } - - return payload; - } -} diff --git a/src/main/java/co/lettermint/endpoints/Endpoint.java b/src/main/java/co/lettermint/endpoints/Endpoint.java deleted file mode 100644 index 0f1bc32..0000000 --- a/src/main/java/co/lettermint/endpoints/Endpoint.java +++ /dev/null @@ -1,15 +0,0 @@ -package co.lettermint.endpoints; - -import co.lettermint.client.LettermintClient; - -/** - * Base class for API endpoints. - */ -public abstract class Endpoint { - - protected final LettermintClient client; - - protected Endpoint(LettermintClient client) { - this.client = client; - } -} diff --git a/src/main/java/co/lettermint/exceptions/ApiException.java b/src/main/java/co/lettermint/exceptions/ApiException.java new file mode 100644 index 0000000..fa14f08 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/ApiException.java @@ -0,0 +1,57 @@ +package co.lettermint.exceptions; + +/** + * The API answered with an error status (4xx or 5xx) and a JSON or empty body. Subclasses cover the + * common statuses; any other 4xx is a plain {@code ApiException}. + */ +public class ApiException extends LettermintException { + private static final long serialVersionUID = 1L; + + private final int status; + private final String code; + private final transient Object details; + private final transient Object body; + + /** + * @param status the HTTP status + * @param message the API's message, or {@code HTTP } + * @param code the machine-readable error code, or null + * @param details additional context from {@code error.details}, or null + * @param body the decoded JSON body, or null for an empty body + */ + public ApiException(int status, String message, String code, Object details, Object body) { + super(message); + this.status = status; + this.code = code; + this.details = details; + this.body = body; + } + + /** + * @return the HTTP status code + */ + public int getStatus() { + return status; + } + + /** + * @return the machine-readable error code from {@code {"error": {"code"}}} or a string {@code error}, or null + */ + public String getCode() { + return code; + } + + /** + * @return additional context from {@code {"error": {"details"}}} (maps, lists and scalars), or null + */ + public Object getDetails() { + return details; + } + + /** + * @return the decoded JSON error body (maps, lists and scalars), or null for an empty body + */ + public Object getBody() { + return body; + } +} diff --git a/src/main/java/co/lettermint/exceptions/AuthenticationException.java b/src/main/java/co/lettermint/exceptions/AuthenticationException.java new file mode 100644 index 0000000..9072029 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/AuthenticationException.java @@ -0,0 +1,17 @@ +package co.lettermint.exceptions; + +/** HTTP 401: the token is missing, invalid or revoked. */ +public class AuthenticationException extends ApiException { + private static final long serialVersionUID = 1L; + + /** + * @param status the HTTP status + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + */ + public AuthenticationException(int status, String message, String code, Object details, Object body) { + super(status, message, code, details, body); + } +} diff --git a/src/main/java/co/lettermint/exceptions/ConflictException.java b/src/main/java/co/lettermint/exceptions/ConflictException.java new file mode 100644 index 0000000..231f55e --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/ConflictException.java @@ -0,0 +1,17 @@ +package co.lettermint.exceptions; + +/** HTTP 409: the request conflicts with the current state, for example an Idempotency-Key reused with a different body. */ +public class ConflictException extends ApiException { + private static final long serialVersionUID = 1L; + + /** + * @param status the HTTP status + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + */ + public ConflictException(int status, String message, String code, Object details, Object body) { + super(status, message, code, details, body); + } +} diff --git a/src/main/java/co/lettermint/exceptions/ConnectionException.java b/src/main/java/co/lettermint/exceptions/ConnectionException.java new file mode 100644 index 0000000..f177992 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/ConnectionException.java @@ -0,0 +1,13 @@ +package co.lettermint.exceptions; + +/** The request could not be sent or the connection failed (DNS, TLS, refused, reset). */ +public class ConnectionException extends LettermintException { + private static final long serialVersionUID = 1L; + + /** + * @param cause the I/O failure + */ + public ConnectionException(Throwable cause) { + super("Could not reach the Lettermint API" + (cause != null && cause.getMessage() != null ? ": " + cause.getMessage() : "."), cause); + } +} diff --git a/src/main/java/co/lettermint/exceptions/HttpRequestException.java b/src/main/java/co/lettermint/exceptions/HttpRequestException.java deleted file mode 100644 index f15c757..0000000 --- a/src/main/java/co/lettermint/exceptions/HttpRequestException.java +++ /dev/null @@ -1,30 +0,0 @@ -package co.lettermint.exceptions; - -/** - * Exception thrown when an HTTP request fails. - */ -public class HttpRequestException extends LettermintException { - - private final int statusCode; - private final String responseBody; - - public HttpRequestException(String message, int statusCode, String responseBody) { - super(message); - this.statusCode = statusCode; - this.responseBody = responseBody; - } - - public HttpRequestException(String message, int statusCode, String responseBody, Throwable cause) { - super(message, cause); - this.statusCode = statusCode; - this.responseBody = responseBody; - } - - public int getStatusCode() { - return statusCode; - } - - public String getResponseBody() { - return responseBody; - } -} diff --git a/src/main/java/co/lettermint/exceptions/LettermintConfigException.java b/src/main/java/co/lettermint/exceptions/LettermintConfigException.java new file mode 100644 index 0000000..9abee54 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/LettermintConfigException.java @@ -0,0 +1,16 @@ +package co.lettermint.exceptions; + +/** + * The client was configured or called incorrectly: a missing or unrecognised token, a token that the + * called method cannot use, an invalid option or an invalid path parameter. Thrown before any request. + */ +public class LettermintConfigException extends LettermintException { + private static final long serialVersionUID = 1L; + + /** + * @param message the message + */ + public LettermintConfigException(String message) { + super(message); + } +} diff --git a/src/main/java/co/lettermint/exceptions/LettermintException.java b/src/main/java/co/lettermint/exceptions/LettermintException.java index 8025c9a..06dbeab 100644 --- a/src/main/java/co/lettermint/exceptions/LettermintException.java +++ b/src/main/java/co/lettermint/exceptions/LettermintException.java @@ -1,14 +1,24 @@ package co.lettermint.exceptions; /** - * Base exception for all Lettermint SDK errors. + * Base class of every exception the SDK throws. Unchecked. + * + *

No exception carries request headers or API tokens, and no message contains them. */ public class LettermintException extends RuntimeException { + private static final long serialVersionUID = 1L; + /** + * @param message the message + */ public LettermintException(String message) { super(message); } + /** + * @param message the message + * @param cause the cause + */ public LettermintException(String message, Throwable cause) { super(message, cause); } diff --git a/src/main/java/co/lettermint/exceptions/LettermintValidationException.java b/src/main/java/co/lettermint/exceptions/LettermintValidationException.java new file mode 100644 index 0000000..82c4ecb --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/LettermintValidationException.java @@ -0,0 +1,27 @@ +package co.lettermint.exceptions; + +/** + * The SDK rejected a request before sending it, for example because of invalid message tags. Unlike + * {@link ValidationException}, the API never saw this request. + */ +public class LettermintValidationException extends LettermintException { + private static final long serialVersionUID = 1L; + + private final String field; + + /** + * @param message the message + * @param field the offending field, for example {@code tags} or {@code messages[2].tags} + */ + public LettermintValidationException(String message, String field) { + super(message); + this.field = field; + } + + /** + * @return the offending field, for example {@code tags} or {@code messages[2].tags}, or null + */ + public String getField() { + return field; + } +} diff --git a/src/main/java/co/lettermint/exceptions/NotFoundException.java b/src/main/java/co/lettermint/exceptions/NotFoundException.java new file mode 100644 index 0000000..282e4cf --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/NotFoundException.java @@ -0,0 +1,17 @@ +package co.lettermint.exceptions; + +/** HTTP 404: the resource does not exist or is not visible to the token. */ +public class NotFoundException extends ApiException { + private static final long serialVersionUID = 1L; + + /** + * @param status the HTTP status + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + */ + public NotFoundException(int status, String message, String code, Object details, Object body) { + super(status, message, code, details, body); + } +} diff --git a/src/main/java/co/lettermint/exceptions/PermissionException.java b/src/main/java/co/lettermint/exceptions/PermissionException.java new file mode 100644 index 0000000..f4b1613 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/PermissionException.java @@ -0,0 +1,17 @@ +package co.lettermint.exceptions; + +/** HTTP 403: the token may not perform this action, or the plan lacks the feature. */ +public class PermissionException extends ApiException { + private static final long serialVersionUID = 1L; + + /** + * @param status the HTTP status + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + */ + public PermissionException(int status, String message, String code, Object details, Object body) { + super(status, message, code, details, body); + } +} diff --git a/src/main/java/co/lettermint/exceptions/RateLimitException.java b/src/main/java/co/lettermint/exceptions/RateLimitException.java new file mode 100644 index 0000000..b66bdb9 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/RateLimitException.java @@ -0,0 +1,30 @@ +package co.lettermint.exceptions; + +import java.time.Duration; + +/** HTTP 429: too many requests. */ +public class RateLimitException extends ApiException { + private static final long serialVersionUID = 1L; + + private final Duration retryAfter; + + /** + * @param status the HTTP status (429) + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + * @param retryAfter the wait from the {@code Retry-After} header, or null + */ + public RateLimitException(int status, String message, String code, Object details, Object body, Duration retryAfter) { + super(status, message, code, details, body); + this.retryAfter = retryAfter; + } + + /** + * @return how long to wait, from the {@code Retry-After} header (seconds or an HTTP date), or null + */ + public Duration getRetryAfter() { + return retryAfter; + } +} diff --git a/src/main/java/co/lettermint/exceptions/RedirectException.java b/src/main/java/co/lettermint/exceptions/RedirectException.java new file mode 100644 index 0000000..c1ace87 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/RedirectException.java @@ -0,0 +1,26 @@ +package co.lettermint.exceptions; + +/** + * The API answered with a redirect (3xx). The SDK never follows redirects, so that tokens are never + * sent to another location. + */ +public class RedirectException extends LettermintException { + private static final long serialVersionUID = 1L; + + private final int status; + + /** + * @param status the HTTP status + */ + public RedirectException(int status) { + super("The Lettermint API answered with a redirect (HTTP " + status + "). Redirects are not followed; check the baseUrl option."); + this.status = status; + } + + /** + * @return the HTTP status code + */ + public int getStatus() { + return status; + } +} diff --git a/src/main/java/co/lettermint/exceptions/ServerException.java b/src/main/java/co/lettermint/exceptions/ServerException.java new file mode 100644 index 0000000..2b3d5bf --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/ServerException.java @@ -0,0 +1,17 @@ +package co.lettermint.exceptions; + +/** HTTP 5xx: a server error with a JSON or empty body. */ +public class ServerException extends ApiException { + private static final long serialVersionUID = 1L; + + /** + * @param status the HTTP status + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + */ + public ServerException(int status, String message, String code, Object details, Object body) { + super(status, message, code, details, body); + } +} diff --git a/src/main/java/co/lettermint/exceptions/TimeoutException.java b/src/main/java/co/lettermint/exceptions/TimeoutException.java new file mode 100644 index 0000000..393d5d5 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/TimeoutException.java @@ -0,0 +1,31 @@ +package co.lettermint.exceptions; + +import java.time.Duration; + +/** + * The request did not complete within the timeout, which covers the whole request: connecting, + * sending, the response headers and the body. The API may still have processed the request; retry a + * send with the same idempotency key. + * + *

Not to be confused with {@link java.util.concurrent.TimeoutException}. + */ +public class TimeoutException extends LettermintException { + private static final long serialVersionUID = 1L; + + private final Duration timeout; + + /** + * @param timeout the timeout that elapsed + */ + public TimeoutException(Duration timeout) { + super("The request to the Lettermint API timed out after " + timeout.toMillis() + " ms."); + this.timeout = timeout; + } + + /** + * @return the timeout that elapsed + */ + public Duration getTimeout() { + return timeout; + } +} diff --git a/src/main/java/co/lettermint/exceptions/UnexpectedResponseException.java b/src/main/java/co/lettermint/exceptions/UnexpectedResponseException.java new file mode 100644 index 0000000..4900372 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/UnexpectedResponseException.java @@ -0,0 +1,40 @@ +package co.lettermint.exceptions; + +/** + * The response could not be decoded: an empty or non-JSON body where JSON was expected, a body of the + * wrong shape, an unexpected status, or an error status with a non-JSON body such as a proxy's HTML page. + */ +public class UnexpectedResponseException extends LettermintException { + private static final long serialVersionUID = 1L; + + private static final int EXCERPT = 200; + + private final int status; + private final String bodyExcerpt; + + /** + * @param message the message + * @param status the HTTP status + * @param body the response body; only the first 200 characters are kept + */ + public UnexpectedResponseException(String message, int status, String body) { + super(message); + this.status = status; + String text = body == null ? "" : body; + this.bodyExcerpt = text.length() > EXCERPT ? text.substring(0, EXCERPT) + "…" : text; + } + + /** + * @return the HTTP status code + */ + public int getStatus() { + return status; + } + + /** + * @return the first 200 characters of the response body + */ + public String getBodyExcerpt() { + return bodyExcerpt; + } +} diff --git a/src/main/java/co/lettermint/exceptions/ValidationException.java b/src/main/java/co/lettermint/exceptions/ValidationException.java index 7dc428b..bba7c07 100644 --- a/src/main/java/co/lettermint/exceptions/ValidationException.java +++ b/src/main/java/co/lettermint/exceptions/ValidationException.java @@ -1,15 +1,31 @@ package co.lettermint.exceptions; -/** - * Exception thrown when API returns validation errors (HTTP 422). - */ -public class ValidationException extends HttpRequestException { +import java.util.List; +import java.util.Map; - public ValidationException(String message, String responseBody) { - super(message, 422, responseBody); +/** HTTP 422: the API rejected the request data. */ +public class ValidationException extends ApiException { + private static final long serialVersionUID = 1L; + + private final transient Map> errors; + + /** + * @param status the HTTP status (422) + * @param message the API's message + * @param code the error code, or null + * @param details the error details, or null + * @param body the decoded body, or null + * @param errors field errors from the {@code {"message", "errors"}} body, or null + */ + public ValidationException(int status, String message, String code, Object details, Object body, Map> errors) { + super(status, message, code, details, body); + this.errors = errors; } - public ValidationException(String message, String responseBody, Throwable cause) { - super(message, 422, responseBody, cause); + /** + * @return field errors from the {@code {"message", "errors"}} body, or null when the API sent none + */ + public Map> getErrors() { + return errors; } } diff --git a/src/main/java/co/lettermint/exceptions/WebhookVerificationException.java b/src/main/java/co/lettermint/exceptions/WebhookVerificationException.java new file mode 100644 index 0000000..ab6c2a0 --- /dev/null +++ b/src/main/java/co/lettermint/exceptions/WebhookVerificationException.java @@ -0,0 +1,57 @@ +package co.lettermint.exceptions; + +/** A webhook delivery could not be verified. Reject the request; do not process its payload. */ +public class WebhookVerificationException extends LettermintException { + private static final long serialVersionUID = 1L; + + /** Why a webhook delivery failed verification. */ + public enum Reason { + /** The {@code X-Lettermint-Signature} header is missing or empty. */ + SIGNATURE_HEADER_MISSING("signature_header_missing"), + /** The signature header is malformed, non-ASCII, repeated or has no {@code t} or {@code v1}. */ + SIGNATURE_HEADER_MALFORMED("signature_header_malformed"), + /** The {@code X-Lettermint-Delivery} header is missing. */ + DELIVERY_HEADER_MISSING("delivery_header_missing"), + /** The {@code X-Lettermint-Delivery} header differs from the signed timestamp, or is repeated. */ + DELIVERY_TIMESTAMP_MISMATCH("delivery_timestamp_mismatch"), + /** The signed timestamp is outside the tolerance. */ + TIMESTAMP_OUT_OF_TOLERANCE("timestamp_out_of_tolerance"), + /** No {@code v1} signature matches. */ + SIGNATURE_MISMATCH("signature_mismatch"), + /** The raw body is missing or empty. */ + BODY_INVALID("body_invalid"), + /** The payload is not a JSON object. */ + PAYLOAD_INVALID("payload_invalid"); + + private final String code; + + Reason(String code) { + this.code = code; + } + + /** + * @return the reason code shared by every Lettermint SDK, for example {@code signature_mismatch} + */ + public String code() { + return code; + } + } + + private final Reason reason; + + /** + * @param reason why verification failed + * @param message the message + */ + public WebhookVerificationException(Reason reason, String message) { + super(message); + this.reason = reason; + } + + /** + * @return why verification failed + */ + public Reason getReason() { + return reason; + } +} diff --git a/src/main/java/co/lettermint/exceptions/webhook/InvalidSignatureException.java b/src/main/java/co/lettermint/exceptions/webhook/InvalidSignatureException.java deleted file mode 100644 index 75653e1..0000000 --- a/src/main/java/co/lettermint/exceptions/webhook/InvalidSignatureException.java +++ /dev/null @@ -1,15 +0,0 @@ -package co.lettermint.exceptions.webhook; - -/** - * Exception thrown when webhook signature validation fails. - */ -public class InvalidSignatureException extends WebhookVerificationException { - - public InvalidSignatureException(String message) { - super(message); - } - - public InvalidSignatureException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/co/lettermint/exceptions/webhook/TimestampToleranceException.java b/src/main/java/co/lettermint/exceptions/webhook/TimestampToleranceException.java deleted file mode 100644 index 085706f..0000000 --- a/src/main/java/co/lettermint/exceptions/webhook/TimestampToleranceException.java +++ /dev/null @@ -1,24 +0,0 @@ -package co.lettermint.exceptions.webhook; - -/** - * Exception thrown when webhook timestamp is outside the allowed tolerance window. - */ -public class TimestampToleranceException extends WebhookVerificationException { - - private final long timestamp; - private final long tolerance; - - public TimestampToleranceException(String message, long timestamp, long tolerance) { - super(message); - this.timestamp = timestamp; - this.tolerance = tolerance; - } - - public long getTimestamp() { - return timestamp; - } - - public long getTolerance() { - return tolerance; - } -} diff --git a/src/main/java/co/lettermint/exceptions/webhook/WebhookVerificationException.java b/src/main/java/co/lettermint/exceptions/webhook/WebhookVerificationException.java deleted file mode 100644 index 36726c8..0000000 --- a/src/main/java/co/lettermint/exceptions/webhook/WebhookVerificationException.java +++ /dev/null @@ -1,17 +0,0 @@ -package co.lettermint.exceptions.webhook; - -import co.lettermint.exceptions.LettermintException; - -/** - * Base exception for webhook verification failures. - */ -public class WebhookVerificationException extends LettermintException { - - public WebhookVerificationException(String message) { - super(message); - } - - public WebhookVerificationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/src/main/java/co/lettermint/models/Attachment.java b/src/main/java/co/lettermint/models/Attachment.java deleted file mode 100644 index abe6c94..0000000 --- a/src/main/java/co/lettermint/models/Attachment.java +++ /dev/null @@ -1,50 +0,0 @@ -package co.lettermint.models; - -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Represents an email attachment. - */ -@JsonInclude(JsonInclude.Include.NON_NULL) -public class Attachment { - - @JsonProperty("filename") - private final String filename; - - @JsonProperty("content") - private final String content; - - @JsonProperty("content_id") - private final String contentId; - - @JsonProperty("content_type") - private final String contentType; - - public Attachment(String filename, String content) { - this(filename, content, null, null); - } - - public Attachment(String filename, String content, String contentId, String contentType) { - this.filename = filename; - this.content = content; - this.contentId = contentId; - this.contentType = contentType; - } - - public String getFilename() { - return filename; - } - - public String getContent() { - return content; - } - - public String getContentId() { - return contentId; - } - - public String getContentType() { - return contentType; - } -} diff --git a/src/main/java/co/lettermint/models/MessageTag.java b/src/main/java/co/lettermint/models/MessageTag.java deleted file mode 100644 index 264c314..0000000 --- a/src/main/java/co/lettermint/models/MessageTag.java +++ /dev/null @@ -1,35 +0,0 @@ -package co.lettermint.models; - -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.util.Locale; -import java.util.regex.Pattern; - -/** A reusable exact-match message tag. */ -public final class MessageTag { - private static final Pattern NAME = Pattern.compile("^[A-Za-z0-9_-]{1,32}$"); - private static final Pattern VALUE = Pattern.compile("^[A-Za-z0-9_-]{1,64}$"); - - @JsonProperty("name") - private final String name; - - @JsonProperty("value") - private final String value; - - public MessageTag(String name, String value) { - if (name == null || !NAME.matcher(name).matches()) { - throw new IllegalArgumentException("Message tag names must match ^[A-Za-z0-9_-]{1,32}$"); - } - if (name.toLowerCase(Locale.ROOT).startsWith("__lettermint")) { - throw new IllegalArgumentException("Message tag names must not start with __lettermint"); - } - if (value == null || !VALUE.matcher(value).matches()) { - throw new IllegalArgumentException("Message tag values must match ^[A-Za-z0-9_-]{1,64}$"); - } - this.name = name; - this.value = value; - } - - public String getName() { return name; } - public String getValue() { return value; } -} diff --git a/src/main/java/co/lettermint/models/SendEmailResponse.java b/src/main/java/co/lettermint/models/SendEmailResponse.java deleted file mode 100644 index a8182b4..0000000 --- a/src/main/java/co/lettermint/models/SendEmailResponse.java +++ /dev/null @@ -1,73 +0,0 @@ -package co.lettermint.models; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -/** - * Response from sending an email. - */ -@JsonIgnoreProperties(ignoreUnknown = true) -public class SendEmailResponse { - - @JsonProperty("message_id") - private String messageId; - - @JsonProperty("status") - private String status; - - @JsonProperty("sandbox") - private Boolean sandbox; - - @JsonProperty("sandbox_result") - private String sandboxResult; - - public SendEmailResponse() { - } - - public SendEmailResponse(String messageId, String status) { - this.messageId = messageId; - this.status = status; - } - - public String getMessageId() { - return messageId; - } - - public void setMessageId(String messageId) { - this.messageId = messageId; - } - - public String getStatus() { - return status; - } - - public void setStatus(String status) { - this.status = status; - } - - public Boolean getSandbox() { - return sandbox; - } - - public void setSandbox(Boolean sandbox) { - this.sandbox = sandbox; - } - - public String getSandboxResult() { - return sandboxResult; - } - - public void setSandboxResult(String sandboxResult) { - this.sandboxResult = sandboxResult; - } - - @Override - public String toString() { - return "SendEmailResponse{" + - "messageId='" + messageId + '\'' + - ", status='" + status + '\'' + - ", sandbox=" + sandbox + - ", sandboxResult='" + sandboxResult + '\'' + - '}'; - } -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsRequest.java b/src/main/java/co/lettermint/models/api/AnalyticsRequest.java deleted file mode 100644 index 21b9bfe..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsRequest.java +++ /dev/null @@ -1,47 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsRequest { - @JsonProperty("metrics") - public List metrics; - - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("timezone") - public String timezone; - - @JsonProperty("include") - public List include; - - @JsonProperty("group_by") - public List groupBy; - - @JsonProperty("filters") - public List filters; - - @JsonProperty("interval") - public String interval; - - @JsonProperty("compare") - public String compare; - - @JsonProperty("include_trend") - public Boolean includeTrend; - - @JsonProperty("sort") - public AnalyticsRequestSort sort; - - @JsonProperty("limit") - public Integer limit; - - @JsonProperty("cursor") - public String cursor; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsRequestFiltersItem.java b/src/main/java/co/lettermint/models/api/AnalyticsRequestFiltersItem.java deleted file mode 100644 index 8c0640d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsRequestFiltersItem.java +++ /dev/null @@ -1,17 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsRequestFiltersItem { - @JsonProperty("dimension") - public String dimension; - - @JsonProperty("operator") - public String operator; - - @JsonProperty("values") - public List values; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsRequestSort.java b/src/main/java/co/lettermint/models/api/AnalyticsRequestSort.java deleted file mode 100644 index 759dfa2..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsRequestSort.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsRequestSort { - @JsonProperty("metric") - public String metric; - - @JsonProperty("direction") - public String direction; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponse.java b/src/main/java/co/lettermint/models/api/AnalyticsResponse.java deleted file mode 100644 index 767888b..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponse { - @JsonProperty("data") - public AnalyticsResponsePayload data; - - @JsonProperty("meta") - public AnalyticsResponseMeta meta; - - @JsonProperty("pagination") - public AnalyticsResponsePagination pagination; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponseData.java b/src/main/java/co/lettermint/models/api/AnalyticsResponseData.java deleted file mode 100644 index 7193a9d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponseData.java +++ /dev/null @@ -1,18 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponseData { - @JsonProperty("data") - public Map data; - - @JsonProperty("meta") - public Map meta; - - @JsonProperty("pagination") - public List pagination; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponseMeta.java b/src/main/java/co/lettermint/models/api/AnalyticsResponseMeta.java deleted file mode 100644 index d585611..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponseMeta.java +++ /dev/null @@ -1,55 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponseMeta { - @JsonProperty("time_basis") - public String timeBasis; - - @JsonProperty("timezone") - public String timezone; - - @JsonProperty("interval") - public String interval; - - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("effective_to") - public String effectiveTo; - - @JsonProperty("alignment") - public String alignment; - - @JsonProperty("generated_at") - public String generatedAt; - - @JsonProperty("available_since") - public String availableSince; - - @JsonProperty("partial") - public Boolean partial; - - @JsonProperty("ongoing") - public Boolean ongoing; - - @JsonProperty("collection_completeness") - public String collectionCompleteness; - - @JsonProperty("last_ingested_at") - public String lastIngestedAt; - - @JsonProperty("metric_definition_version") - public String metricDefinitionVersion; - - @JsonProperty("ranked_group_limit") - public Integer rankedGroupLimit; - - @JsonProperty("comparison") - public AnalyticsResponseMetaComparison comparison; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponseMetaComparison.java b/src/main/java/co/lettermint/models/api/AnalyticsResponseMetaComparison.java deleted file mode 100644 index b425200..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponseMetaComparison.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponseMetaComparison { - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("partial") - public Boolean partial; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePagination.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePagination.java deleted file mode 100644 index 872c1ae..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePagination.java +++ /dev/null @@ -1,19 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePagination { - @JsonProperty("total_groups") - public Integer totalGroups; - - @JsonProperty("returned_groups") - public Integer returnedGroups; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("truncated") - public Boolean truncated; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayload.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayload.java deleted file mode 100644 index ab77108..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayload.java +++ /dev/null @@ -1,17 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayload { - @JsonProperty("summary") - public AnalyticsResponsePayloadSummary summary; - - @JsonProperty("time_series") - public List timeSeries; - - @JsonProperty("breakdown") - public List breakdown; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItem.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItem.java deleted file mode 100644 index 4d02d42..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItem.java +++ /dev/null @@ -1,27 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItem { - @JsonProperty("metrics") - public AnalyticsResponsePayloadBreakdownItemMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadBreakdownItemRateBases rateBases; - - @JsonProperty("previous") - public AnalyticsResponsePayloadBreakdownItemPrevious previous; - - @JsonProperty("change") - public Map> change; - - @JsonProperty("dimensions") - public Map dimensions; - - @JsonProperty("trend") - public List trend; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemMetrics.java deleted file mode 100644 index 31ea9ab..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPrevious.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPrevious.java deleted file mode 100644 index dfc89a7..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPrevious.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPrevious { - @JsonProperty("metrics") - public AnalyticsResponsePayloadBreakdownItemPreviousMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBases rateBases; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousMetrics.java deleted file mode 100644 index ac713b7..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBases.java deleted file mode 100644 index 532240a..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesBounceRate.java deleted file mode 100644 index b9a9394..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesComplaintRate.java deleted file mode 100644 index ed35724..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeferralRate.java deleted file mode 100644 index 2d8151d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeliveryRate.java deleted file mode 100644 index 125c65c..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index b97100f..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanClickRate.java deleted file mode 100644 index fdb1830..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanOpenRate.java deleted file mode 100644 index 7eabfcd..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemPreviousRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBases.java deleted file mode 100644 index 3be8ed4..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadBreakdownItemRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesBounceRate.java deleted file mode 100644 index 432ffdf..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesComplaintRate.java deleted file mode 100644 index c7bf65e..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeferralRate.java deleted file mode 100644 index 28d88f9..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeliveryRate.java deleted file mode 100644 index 441280b..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index a21bca0..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanClickRate.java deleted file mode 100644 index 2c86fdb..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanOpenRate.java deleted file mode 100644 index 4fe1725..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItem.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItem.java deleted file mode 100644 index 5ac76cd..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItem { - @JsonProperty("metrics") - public AnalyticsResponsePayloadBreakdownItemTrendItemMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBases rateBases; - - @JsonProperty("previous") - public AnalyticsResponsePayloadBreakdownItemTrendItemPrevious previous; - - @JsonProperty("change") - public Map> change; - - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("available") - public Boolean available; - - @JsonProperty("partial") - public Boolean partial; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemMetrics.java deleted file mode 100644 index 8369809..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPrevious.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPrevious.java deleted file mode 100644 index 8d16473..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPrevious.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPrevious { - @JsonProperty("metrics") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBases rateBases; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousMetrics.java deleted file mode 100644 index b5b4404..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBases.java deleted file mode 100644 index 770b2c5..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesBounceRate.java deleted file mode 100644 index 655fd4f..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesComplaintRate.java deleted file mode 100644 index 4229ce8..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeferralRate.java deleted file mode 100644 index a4e9807..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeliveryRate.java deleted file mode 100644 index 6458cdf..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index 8a690c2..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanClickRate.java deleted file mode 100644 index 21fc074..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanOpenRate.java deleted file mode 100644 index 0508d8f..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemPreviousRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBases.java deleted file mode 100644 index df9b1b8..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesBounceRate.java deleted file mode 100644 index d30d7fc..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesComplaintRate.java deleted file mode 100644 index f2cca1d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeferralRate.java deleted file mode 100644 index f8df528..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeliveryRate.java deleted file mode 100644 index 9846da7..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index 3976f25..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanClickRate.java deleted file mode 100644 index 8dce4cd..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanOpenRate.java deleted file mode 100644 index e6efca5..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadBreakdownItemTrendItemRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummary.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummary.java deleted file mode 100644 index be479ee..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummary.java +++ /dev/null @@ -1,20 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummary { - @JsonProperty("metrics") - public AnalyticsResponsePayloadSummaryMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadSummaryRateBases rateBases; - - @JsonProperty("previous") - public AnalyticsResponsePayloadSummaryPrevious previous; - - @JsonProperty("change") - public Map> change; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryMetrics.java deleted file mode 100644 index 343ddd9..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPrevious.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPrevious.java deleted file mode 100644 index c551806..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPrevious.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPrevious { - @JsonProperty("metrics") - public AnalyticsResponsePayloadSummaryPreviousMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadSummaryPreviousRateBases rateBases; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousMetrics.java deleted file mode 100644 index 4c27652..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBases.java deleted file mode 100644 index e08e55c..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadSummaryPreviousRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesBounceRate.java deleted file mode 100644 index dd2cd0e..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesComplaintRate.java deleted file mode 100644 index d7df134..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeferralRate.java deleted file mode 100644 index f46296d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeliveryRate.java deleted file mode 100644 index 8235aef..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index fba38f7..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanClickRate.java deleted file mode 100644 index 20a2558..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanOpenRate.java deleted file mode 100644 index 6cc249a..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryPreviousRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryPreviousRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBases.java deleted file mode 100644 index 484032d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadSummaryRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadSummaryRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadSummaryRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadSummaryRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadSummaryRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadSummaryRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadSummaryRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesBounceRate.java deleted file mode 100644 index 85d2d88..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesComplaintRate.java deleted file mode 100644 index 9d16c6b..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeferralRate.java deleted file mode 100644 index 729b8cf..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeliveryRate.java deleted file mode 100644 index cd454e0..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index ca9777d..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanClickRate.java deleted file mode 100644 index 4eb3774..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanOpenRate.java deleted file mode 100644 index f881be4..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadSummaryRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadSummaryRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItem.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItem.java deleted file mode 100644 index 620126e..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItem.java +++ /dev/null @@ -1,32 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItem { - @JsonProperty("metrics") - public AnalyticsResponsePayloadTimeSeriesItemMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadTimeSeriesItemRateBases rateBases; - - @JsonProperty("previous") - public AnalyticsResponsePayloadTimeSeriesItemPrevious previous; - - @JsonProperty("change") - public Map> change; - - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("available") - public Boolean available; - - @JsonProperty("partial") - public Boolean partial; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemMetrics.java deleted file mode 100644 index 9ae3dd0..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPrevious.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPrevious.java deleted file mode 100644 index 81569a2..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPrevious.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPrevious { - @JsonProperty("metrics") - public AnalyticsResponsePayloadTimeSeriesItemPreviousMetrics metrics; - - @JsonProperty("rate_bases") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBases rateBases; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousMetrics.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousMetrics.java deleted file mode 100644 index 380c587..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousMetrics.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousMetrics { - @JsonProperty("accepted") - public Integer accepted; - - @JsonProperty("processed") - public Integer processed; - - @JsonProperty("suppressed") - public Integer suppressed; - - @JsonProperty("policy_rejected") - public Integer policyRejected; - - @JsonProperty("application_failed") - public Integer applicationFailed; - - @JsonProperty("mta_accepted") - public Integer mtaAccepted; - - @JsonProperty("canceled") - public Integer canceled; - - @JsonProperty("messages") - public Integer messages; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("bounced") - public Integer bounced; - - @JsonProperty("soft_bounced") - public Integer softBounced; - - @JsonProperty("administratively_bounced") - public Integer administrativelyBounced; - - @JsonProperty("deferred_recipients") - public Integer deferredRecipients; - - @JsonProperty("deferred_events") - public Integer deferredEvents; - - @JsonProperty("delivery_attempts") - public Integer deliveryAttempts; - - @JsonProperty("attempted_recipients") - public Integer attemptedRecipients; - - @JsonProperty("transport_outcome_recipients") - public Integer transportOutcomeRecipients; - - @JsonProperty("effective_delivered") - public Integer effectiveDelivered; - - @JsonProperty("open_tracked_delivered") - public Integer openTrackedDelivered; - - @JsonProperty("click_tracked_delivered") - public Integer clickTrackedDelivered; - - @JsonProperty("out_of_band_bounced_recipients") - public Integer outOfBandBouncedRecipients; - - @JsonProperty("out_of_band_bounce_events") - public Integer outOfBandBounceEvents; - - @JsonProperty("complained") - public Integer complained; - - @JsonProperty("unsubscribed") - public Integer unsubscribed; - - @JsonProperty("human_opens") - public Integer humanOpens; - - @JsonProperty("human_opens_events") - public Integer humanOpensEvents; - - @JsonProperty("human_clicks") - public Integer humanClicks; - - @JsonProperty("human_clicks_events") - public Integer humanClicksEvents; - - @JsonProperty("machine_opens") - public Integer machineOpens; - - @JsonProperty("machine_opens_events") - public Integer machineOpensEvents; - - @JsonProperty("machine_clicks") - public Integer machineClicks; - - @JsonProperty("machine_clicks_events") - public Integer machineClicksEvents; - - @JsonProperty("privacy_opens") - public Integer privacyOpens; - - @JsonProperty("privacy_opens_events") - public Integer privacyOpensEvents; - - @JsonProperty("privacy_clicks") - public Integer privacyClicks; - - @JsonProperty("privacy_clicks_events") - public Integer privacyClicksEvents; - - @JsonProperty("bot_opens") - public Integer botOpens; - - @JsonProperty("bot_opens_events") - public Integer botOpensEvents; - - @JsonProperty("bot_clicks") - public Integer botClicks; - - @JsonProperty("bot_clicks_events") - public Integer botClicksEvents; - - @JsonProperty("scanner_opens") - public Integer scannerOpens; - - @JsonProperty("scanner_opens_events") - public Integer scannerOpensEvents; - - @JsonProperty("scanner_clicks") - public Integer scannerClicks; - - @JsonProperty("scanner_clicks_events") - public Integer scannerClicksEvents; - - @JsonProperty("observed_opens") - public Integer observedOpens; - - @JsonProperty("observed_opens_events") - public Integer observedOpensEvents; - - @JsonProperty("observed_clicks") - public Integer observedClicks; - - @JsonProperty("observed_clicks_events") - public Integer observedClicksEvents; - - @JsonProperty("delivery_rate") - public Double deliveryRate; - - @JsonProperty("effective_delivery_rate") - public Double effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public Double bounceRate; - - @JsonProperty("deferral_rate") - public Double deferralRate; - - @JsonProperty("complaint_rate") - public Double complaintRate; - - @JsonProperty("human_open_rate") - public Double humanOpenRate; - - @JsonProperty("human_click_rate") - public Double humanClickRate; - - @JsonProperty("processing_latency_p50_ms") - public Double processingLatencyP50Ms; - - @JsonProperty("processing_latency_p95_ms") - public Double processingLatencyP95Ms; - - @JsonProperty("processing_latency_p99_ms") - public Double processingLatencyP99Ms; - - @JsonProperty("processing_latency_samples") - public Integer processingLatencySamples; - - @JsonProperty("delivery_latency_p50_ms") - public Double deliveryLatencyP50Ms; - - @JsonProperty("delivery_latency_p95_ms") - public Double deliveryLatencyP95Ms; - - @JsonProperty("delivery_latency_p99_ms") - public Double deliveryLatencyP99Ms; - - @JsonProperty("delivery_latency_samples") - public Integer deliveryLatencySamples; - - @JsonProperty("total_latency_p50_ms") - public Double totalLatencyP50Ms; - - @JsonProperty("total_latency_p95_ms") - public Double totalLatencyP95Ms; - - @JsonProperty("total_latency_p99_ms") - public Double totalLatencyP99Ms; - - @JsonProperty("total_latency_samples") - public Integer totalLatencySamples; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBases.java deleted file mode 100644 index dbc22af..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesBounceRate.java deleted file mode 100644 index 47954ba..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesComplaintRate.java deleted file mode 100644 index 6aa95ac..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeferralRate.java deleted file mode 100644 index 97fbc6f..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeliveryRate.java deleted file mode 100644 index 84d6a29..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index 9ec4965..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanClickRate.java deleted file mode 100644 index ca9f0c5..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanOpenRate.java deleted file mode 100644 index 9f49557..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemPreviousRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBases.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBases.java deleted file mode 100644 index 1e329e2..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBases.java +++ /dev/null @@ -1,28 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBases { - @JsonProperty("delivery_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesDeliveryRate deliveryRate; - - @JsonProperty("effective_delivery_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesEffectiveDeliveryRate effectiveDeliveryRate; - - @JsonProperty("bounce_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesBounceRate bounceRate; - - @JsonProperty("deferral_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesDeferralRate deferralRate; - - @JsonProperty("complaint_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesComplaintRate complaintRate; - - @JsonProperty("human_open_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanOpenRate humanOpenRate; - - @JsonProperty("human_click_rate") - public AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanClickRate humanClickRate; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesBounceRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesBounceRate.java deleted file mode 100644 index c8ab78c..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesBounceRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesBounceRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesComplaintRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesComplaintRate.java deleted file mode 100644 index 7a33c62..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesComplaintRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesComplaintRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeferralRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeferralRate.java deleted file mode 100644 index c46476b..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeferralRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesDeferralRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeliveryRate.java deleted file mode 100644 index 9bb3565..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesEffectiveDeliveryRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesEffectiveDeliveryRate.java deleted file mode 100644 index 24bfcdf..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesEffectiveDeliveryRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesEffectiveDeliveryRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanClickRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanClickRate.java deleted file mode 100644 index c367ed6..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanClickRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanClickRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanOpenRate.java b/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanOpenRate.java deleted file mode 100644 index 3fcb551..0000000 --- a/src/main/java/co/lettermint/models/api/AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanOpenRate.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class AnalyticsResponsePayloadTimeSeriesItemRateBasesHumanOpenRate { - @JsonProperty("numerator") - public Integer numerator; - - @JsonProperty("denominator") - public Integer denominator; -} diff --git a/src/main/java/co/lettermint/models/api/AttachmentDelivery.java b/src/main/java/co/lettermint/models/api/AttachmentDelivery.java deleted file mode 100644 index d5e683c..0000000 --- a/src/main/java/co/lettermint/models/api/AttachmentDelivery.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class AttachmentDelivery { - public static final String INLINE = "inline"; - public static final String URL = "url"; - - private AttachmentDelivery() {} -} diff --git a/src/main/java/co/lettermint/models/api/BlockedFileTypesResponse.java b/src/main/java/co/lettermint/models/api/BlockedFileTypesResponse.java deleted file mode 100644 index e00f2c3..0000000 --- a/src/main/java/co/lettermint/models/api/BlockedFileTypesResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class BlockedFileTypesResponse { - @JsonProperty("extensions") - public List extensions; - - @JsonProperty("mime_types") - public List mimeTypes; -} diff --git a/src/main/java/co/lettermint/models/api/BuiltInTeamRole.java b/src/main/java/co/lettermint/models/api/BuiltInTeamRole.java deleted file mode 100644 index 69ede0c..0000000 --- a/src/main/java/co/lettermint/models/api/BuiltInTeamRole.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class BuiltInTeamRole { - public static final String OWNER = "owner"; - public static final String ADMIN = "admin"; - public static final String MEMBER = "member"; - - private BuiltInTeamRole() {} -} diff --git a/src/main/java/co/lettermint/models/api/CancelScheduledMessageResponse.java b/src/main/java/co/lettermint/models/api/CancelScheduledMessageResponse.java deleted file mode 100644 index 5eeb1cd..0000000 --- a/src/main/java/co/lettermint/models/api/CancelScheduledMessageResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CancelScheduledMessageResponse extends RescheduleMessageResponse { -} diff --git a/src/main/java/co/lettermint/models/api/CursorPaginator.java b/src/main/java/co/lettermint/models/api/CursorPaginator.java deleted file mode 100644 index d2f99fc..0000000 --- a/src/main/java/co/lettermint/models/api/CursorPaginator.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class CursorPaginator { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/DeliveryMode.java b/src/main/java/co/lettermint/models/api/DeliveryMode.java deleted file mode 100644 index 7af48f2..0000000 --- a/src/main/java/co/lettermint/models/api/DeliveryMode.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class DeliveryMode { - public static final String LIVE = "live"; - public static final String SANDBOX = "sandbox"; - - private DeliveryMode() {} -} diff --git a/src/main/java/co/lettermint/models/api/DkimMode.java b/src/main/java/co/lettermint/models/api/DkimMode.java deleted file mode 100644 index d407c19..0000000 --- a/src/main/java/co/lettermint/models/api/DkimMode.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class DkimMode { - public static final String LEGACYTXT = "legacy_txt"; - public static final String MANAGEDCNAME = "managed_cname"; - - private DkimMode() {} -} diff --git a/src/main/java/co/lettermint/models/api/DnsRecordPurpose.java b/src/main/java/co/lettermint/models/api/DnsRecordPurpose.java deleted file mode 100644 index d6ecdc3..0000000 --- a/src/main/java/co/lettermint/models/api/DnsRecordPurpose.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.lettermint.models.api; - -public final class DnsRecordPurpose { - public static final String RETURNPATH = "return_path"; - public static final String DMARC = "dmarc"; - public static final String DKIMLEGACY = "dkim_legacy"; - public static final String DKIMPRIMARY = "dkim_primary"; - public static final String DKIMSECONDARY = "dkim_secondary"; - - private DnsRecordPurpose() {} -} diff --git a/src/main/java/co/lettermint/models/api/DnsRecordStatus.java b/src/main/java/co/lettermint/models/api/DnsRecordStatus.java deleted file mode 100644 index 3179b75..0000000 --- a/src/main/java/co/lettermint/models/api/DnsRecordStatus.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class DnsRecordStatus { - public static final String ACTIVE = "active"; - public static final String FAILED = "failed"; - public static final String PENDING = "pending"; - - private DnsRecordStatus() {} -} diff --git a/src/main/java/co/lettermint/models/api/DnsVerificationScope.java b/src/main/java/co/lettermint/models/api/DnsVerificationScope.java deleted file mode 100644 index dc5bfa7..0000000 --- a/src/main/java/co/lettermint/models/api/DnsVerificationScope.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -public final class DnsVerificationScope { - public static final String REQUIRED = "required"; - public static final String RECOMMENDED = "recommended"; - public static final String MIGRATION = "migration"; - public static final String DEPRECATED = "deprecated"; - - private DnsVerificationScope() {} -} diff --git a/src/main/java/co/lettermint/models/api/DomainData.java b/src/main/java/co/lettermint/models/api/DomainData.java deleted file mode 100644 index 0b00fd5..0000000 --- a/src/main/java/co/lettermint/models/api/DomainData.java +++ /dev/null @@ -1,33 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainData { - @JsonProperty("id") - public String id; - - @JsonProperty("domain") - public String domain; - - @JsonProperty("dkim_mode") - public String dkimMode; - - @JsonProperty("rotation_ready") - public Boolean rotationReady; - - @JsonProperty("status_changed_at") - public String statusChangedAt; - - @JsonProperty("dns_records") - public List dnsRecords; - - @JsonProperty("projects") - public List> projects; - - @JsonProperty("created_at") - public String createdAt; -} diff --git a/src/main/java/co/lettermint/models/api/DomainDestroyResponse.java b/src/main/java/co/lettermint/models/api/DomainDestroyResponse.java deleted file mode 100644 index 7332b28..0000000 --- a/src/main/java/co/lettermint/models/api/DomainDestroyResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainDestroyResponse { - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/DomainDnsRecordData.java b/src/main/java/co/lettermint/models/api/DomainDnsRecordData.java deleted file mode 100644 index fd00586..0000000 --- a/src/main/java/co/lettermint/models/api/DomainDnsRecordData.java +++ /dev/null @@ -1,40 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainDnsRecordData { - @JsonProperty("id") - public String id; - - @JsonProperty("type") - public String type; - - @JsonProperty("hostname") - public String hostname; - - @JsonProperty("fqdn") - public String fqdn; - - @JsonProperty("content") - public String content; - - @JsonProperty("status") - public String status; - - @JsonProperty("purpose") - public String purpose; - - @JsonProperty("verification_scope") - public String verificationScope; - - @JsonProperty("required_for_verification") - public Boolean requiredForVerification; - - @JsonProperty("verified_at") - public String verifiedAt; - - @JsonProperty("last_checked_at") - public String lastCheckedAt; -} diff --git a/src/main/java/co/lettermint/models/api/DomainIndexResponse.java b/src/main/java/co/lettermint/models/api/DomainIndexResponse.java deleted file mode 100644 index 7c4ab13..0000000 --- a/src/main/java/co/lettermint/models/api/DomainIndexResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainIndexResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/DomainListData.java b/src/main/java/co/lettermint/models/api/DomainListData.java deleted file mode 100644 index 729d540..0000000 --- a/src/main/java/co/lettermint/models/api/DomainListData.java +++ /dev/null @@ -1,25 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainListData { - @JsonProperty("id") - public String id; - - @JsonProperty("domain") - public String domain; - - @JsonProperty("status") - public String status; - - @JsonProperty("dkim_mode") - public String dkimMode; - - @JsonProperty("status_changed_at") - public String statusChangedAt; - - @JsonProperty("created_at") - public String createdAt; -} diff --git a/src/main/java/co/lettermint/models/api/DomainStatus.java b/src/main/java/co/lettermint/models/api/DomainStatus.java deleted file mode 100644 index 4fd0b1c..0000000 --- a/src/main/java/co/lettermint/models/api/DomainStatus.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -public final class DomainStatus { - public static final String VERIFIED = "verified"; - public static final String PARTIALLYVERIFIED = "partially_verified"; - public static final String PENDINGVERIFICATION = "pending_verification"; - public static final String FAILEDVERIFICATION = "failed_verification"; - - private DomainStatus() {} -} diff --git a/src/main/java/co/lettermint/models/api/DomainUpdateProjectsResponse.java b/src/main/java/co/lettermint/models/api/DomainUpdateProjectsResponse.java deleted file mode 100644 index 7b987b1..0000000 --- a/src/main/java/co/lettermint/models/api/DomainUpdateProjectsResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainUpdateProjectsResponse { - @JsonProperty("data") - public DomainData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/DomainVerifyDnsRecordsResponse.java b/src/main/java/co/lettermint/models/api/DomainVerifyDnsRecordsResponse.java deleted file mode 100644 index 79e2aae..0000000 --- a/src/main/java/co/lettermint/models/api/DomainVerifyDnsRecordsResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainVerifyDnsRecordsResponse { - @JsonProperty("message") - public String message; - - @JsonProperty("recommended_failed_records") - public List> recommendedFailedRecords; -} diff --git a/src/main/java/co/lettermint/models/api/DomainVerifySpecificDnsRecordResponse.java b/src/main/java/co/lettermint/models/api/DomainVerifySpecificDnsRecordResponse.java deleted file mode 100644 index 01cf44f..0000000 --- a/src/main/java/co/lettermint/models/api/DomainVerifySpecificDnsRecordResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class DomainVerifySpecificDnsRecordResponse { - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/GetReportForwardingResponse.java b/src/main/java/co/lettermint/models/api/GetReportForwardingResponse.java deleted file mode 100644 index 0c8206e..0000000 --- a/src/main/java/co/lettermint/models/api/GetReportForwardingResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class GetReportForwardingResponse { - @JsonProperty("data") - public ReportForwardingResource data; -} diff --git a/src/main/java/co/lettermint/models/api/InitialRoutes.java b/src/main/java/co/lettermint/models/api/InitialRoutes.java deleted file mode 100644 index 46eddb3..0000000 --- a/src/main/java/co/lettermint/models/api/InitialRoutes.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class InitialRoutes { - public static final String BOTH = "both"; - public static final String TRANSACTIONAL = "transactional"; - public static final String BROADCAST = "broadcast"; - - private InitialRoutes() {} -} diff --git a/src/main/java/co/lettermint/models/api/MessageAttachmentData.java b/src/main/java/co/lettermint/models/api/MessageAttachmentData.java deleted file mode 100644 index 316ac89..0000000 --- a/src/main/java/co/lettermint/models/api/MessageAttachmentData.java +++ /dev/null @@ -1,19 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageAttachmentData { - @JsonProperty("size") - public Integer size; - - @JsonProperty("filename") - public String filename; - - @JsonProperty("content_id") - public String contentId; - - @JsonProperty("content_type") - public String contentType; -} diff --git a/src/main/java/co/lettermint/models/api/MessageData.java b/src/main/java/co/lettermint/models/api/MessageData.java deleted file mode 100644 index 40d737f..0000000 --- a/src/main/java/co/lettermint/models/api/MessageData.java +++ /dev/null @@ -1,75 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageData { - @JsonProperty("id") - public String id; - - @JsonProperty("type") - public String type; - - @JsonProperty("status") - public String status; - - @JsonProperty("status_changed_at") - public String statusChangedAt; - - @JsonProperty("scheduled_at") - public String scheduledAt; - - @JsonProperty("tag") - public String tag; - - @JsonProperty("tags") - public List> tags; - - @JsonProperty("from_email") - public String fromEmail; - - @JsonProperty("from_name") - public String fromName; - - @JsonProperty("reply_to") - public List replyTo; - - @JsonProperty("subject") - public String subject; - - @JsonProperty("to") - public List to; - - @JsonProperty("cc") - public List cc; - - @JsonProperty("bcc") - public List bcc; - - @JsonProperty("attachments") - public List attachments; - - @JsonProperty("metadata") - public Map metadata; - - @JsonProperty("spam_score") - public Double spamScore; - - @JsonProperty("spam_symbols") - public List spamSymbols; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("delivery_mode") - public String deliveryMode; - - @JsonProperty("sandbox_result") - public String sandboxResult; -} diff --git a/src/main/java/co/lettermint/models/api/MessageEventData.java b/src/main/java/co/lettermint/models/api/MessageEventData.java deleted file mode 100644 index a2efb0d..0000000 --- a/src/main/java/co/lettermint/models/api/MessageEventData.java +++ /dev/null @@ -1,27 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageEventData { - @JsonProperty("message_id") - public String messageId; - - @JsonProperty("event") - public String event; - - @JsonProperty("tag") - public String tag; - - @JsonProperty("tags") - public List> tags; - - @JsonProperty("metadata") - public Map metadata; - - @JsonProperty("timestamp") - public String timestamp; -} diff --git a/src/main/java/co/lettermint/models/api/MessageEventType.java b/src/main/java/co/lettermint/models/api/MessageEventType.java deleted file mode 100644 index 9d4ba2a..0000000 --- a/src/main/java/co/lettermint/models/api/MessageEventType.java +++ /dev/null @@ -1,30 +0,0 @@ -package co.lettermint.models.api; - -public final class MessageEventType { - public static final String SCHEDULED = "scheduled"; - public static final String RESCHEDULED = "rescheduled"; - public static final String CANCELED = "canceled"; - public static final String RELEASED = "released"; - public static final String QUEUED = "queued"; - public static final String PROCESSED = "processed"; - public static final String SUPPRESSED = "suppressed"; - public static final String DELIVERED = "delivered"; - public static final String AUTOREPLIED = "auto_replied"; - public static final String SOFTBOUNCED = "soft_bounced"; - public static final String HARDBOUNCED = "hard_bounced"; - public static final String SPAMCOMPLAINT = "spam_complaint"; - public static final String FAILED = "failed"; - public static final String BLOCKED = "blocked"; - public static final String POLICYREJECTED = "policy_rejected"; - public static final String UNSUBSCRIBED = "unsubscribed"; - public static final String OPENED = "opened"; - public static final String CLICKED = "clicked"; - public static final String INBOUNDRECEIVED = "inbound_received"; - public static final String INBOUNDQUEUED = "inbound_queued"; - public static final String INBOUNDSPAMBLOCKED = "inbound_spam_blocked"; - public static final String INBOUNDRELEASED = "inbound_released"; - public static final String INBOUNDPROCESSED = "inbound_processed"; - public static final String INBOUNDRETRY = "inbound_retry"; - - private MessageEventType() {} -} diff --git a/src/main/java/co/lettermint/models/api/MessageEventsResponse.java b/src/main/java/co/lettermint/models/api/MessageEventsResponse.java deleted file mode 100644 index a866a0e..0000000 --- a/src/main/java/co/lettermint/models/api/MessageEventsResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageEventsResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("links") - public List links; - - @JsonProperty("meta") - public Map meta; -} diff --git a/src/main/java/co/lettermint/models/api/MessageIndexResponse.java b/src/main/java/co/lettermint/models/api/MessageIndexResponse.java deleted file mode 100644 index 7a1db83..0000000 --- a/src/main/java/co/lettermint/models/api/MessageIndexResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageIndexResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("links") - public List links; - - @JsonProperty("meta") - public Map meta; -} diff --git a/src/main/java/co/lettermint/models/api/MessageListData.java b/src/main/java/co/lettermint/models/api/MessageListData.java deleted file mode 100644 index 30efbf6..0000000 --- a/src/main/java/co/lettermint/models/api/MessageListData.java +++ /dev/null @@ -1,63 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageListData { - @JsonProperty("id") - public String id; - - @JsonProperty("type") - public String type; - - @JsonProperty("status") - public String status; - - @JsonProperty("scheduled_at") - public String scheduledAt; - - @JsonProperty("spam_score") - public Double spamScore; - - @JsonProperty("from_email") - public String fromEmail; - - @JsonProperty("from_name") - public String fromName; - - @JsonProperty("subject") - public String subject; - - @JsonProperty("to") - public List to; - - @JsonProperty("cc") - public List cc; - - @JsonProperty("bcc") - public List bcc; - - @JsonProperty("reply_to") - public List replyTo; - - @JsonProperty("tag") - public String tag; - - @JsonProperty("tags") - public List> tags; - - @JsonProperty("status_changed_at") - public String statusChangedAt; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("delivery_mode") - public String deliveryMode; - - @JsonProperty("sandbox_result") - public String sandboxResult; -} diff --git a/src/main/java/co/lettermint/models/api/MessageRecipientData.java b/src/main/java/co/lettermint/models/api/MessageRecipientData.java deleted file mode 100644 index c15c50f..0000000 --- a/src/main/java/co/lettermint/models/api/MessageRecipientData.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageRecipientData { - @JsonProperty("email") - public String email; - - @JsonProperty("name") - public String name; - - @JsonProperty("sandbox_result") - public String sandboxResult; -} diff --git a/src/main/java/co/lettermint/models/api/MessageStatsData.java b/src/main/java/co/lettermint/models/api/MessageStatsData.java deleted file mode 100644 index a4cd8b6..0000000 --- a/src/main/java/co/lettermint/models/api/MessageStatsData.java +++ /dev/null @@ -1,19 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class MessageStatsData { - @JsonProperty("messages_transactional") - public Integer messagesTransactional; - - @JsonProperty("messages_broadcast") - public Integer messagesBroadcast; - - @JsonProperty("messages_inbound") - public Integer messagesInbound; - - @JsonProperty("deliverability") - public Double deliverability; -} diff --git a/src/main/java/co/lettermint/models/api/MessageStatus.java b/src/main/java/co/lettermint/models/api/MessageStatus.java deleted file mode 100644 index 1232cdd..0000000 --- a/src/main/java/co/lettermint/models/api/MessageStatus.java +++ /dev/null @@ -1,23 +0,0 @@ -package co.lettermint.models.api; - -public final class MessageStatus { - public static final String SCHEDULED = "scheduled"; - public static final String PENDING = "pending"; - public static final String QUEUED = "queued"; - public static final String QUARANTINED = "quarantined"; - public static final String SUPPRESSED = "suppressed"; - public static final String PROCESSED = "processed"; - public static final String DELIVERED = "delivered"; - public static final String OPENED = "opened"; - public static final String CLICKED = "clicked"; - public static final String SOFTBOUNCED = "soft_bounced"; - public static final String HARDBOUNCED = "hard_bounced"; - public static final String SPAMCOMPLAINT = "spam_complaint"; - public static final String FAILED = "failed"; - public static final String BLOCKED = "blocked"; - public static final String POLICYREJECTED = "policy_rejected"; - public static final String UNSUBSCRIBED = "unsubscribed"; - public static final String CANCELED = "canceled"; - - private MessageStatus() {} -} diff --git a/src/main/java/co/lettermint/models/api/MessageType.java b/src/main/java/co/lettermint/models/api/MessageType.java deleted file mode 100644 index 5f6e989..0000000 --- a/src/main/java/co/lettermint/models/api/MessageType.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class MessageType { - public static final String INBOUND = "inbound"; - public static final String OUTBOUND = "outbound"; - - private MessageType() {} -} diff --git a/src/main/java/co/lettermint/models/api/OptionalNullable.java b/src/main/java/co/lettermint/models/api/OptionalNullable.java deleted file mode 100644 index b892b92..0000000 --- a/src/main/java/co/lettermint/models/api/OptionalNullable.java +++ /dev/null @@ -1,57 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonValue; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.BeanProperty; -import com.fasterxml.jackson.databind.DeserializationContext; -import com.fasterxml.jackson.databind.JavaType; -import com.fasterxml.jackson.databind.JsonDeserializer; -import com.fasterxml.jackson.databind.annotation.JsonDeserialize; -import com.fasterxml.jackson.databind.deser.ContextualDeserializer; -import java.io.IOException; - -@JsonDeserialize(using = OptionalNullable.Deserializer.class) -public final class OptionalNullable { - private final T value; - - private OptionalNullable(T value) { - this.value = value; - } - - public static OptionalNullable of(T value) { - return new OptionalNullable<>(value); - } - - public static OptionalNullable nullValue() { - return new OptionalNullable<>(null); - } - - @JsonValue - public T getValue() { - return value; - } - - public static final class Deserializer extends JsonDeserializer> implements ContextualDeserializer { - private final JavaType valueType; - - public Deserializer() { this(null); } - - private Deserializer(JavaType valueType) { this.valueType = valueType; } - - @Override - public JsonDeserializer createContextual(DeserializationContext context, BeanProperty property) { - JavaType type = property == null ? context.getContextualType() : property.getType(); - return new Deserializer(type.containedType(0)); - } - - @Override - public OptionalNullable getNullValue(DeserializationContext context) { - return OptionalNullable.nullValue(); - } - - @Override - public OptionalNullable deserialize(JsonParser parser, DeserializationContext context) throws IOException { - return OptionalNullable.of(context.readValue(parser, valueType)); - } - } -} diff --git a/src/main/java/co/lettermint/models/api/Plan.java b/src/main/java/co/lettermint/models/api/Plan.java deleted file mode 100644 index 6c4b681..0000000 --- a/src/main/java/co/lettermint/models/api/Plan.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -public final class Plan { - public static final String FREE = "free"; - public static final String STARTER = "starter"; - public static final String GROWTH = "growth"; - public static final String PRO = "pro"; - - private Plan() {} -} diff --git a/src/main/java/co/lettermint/models/api/ProcessInboundMessageResponse.java b/src/main/java/co/lettermint/models/api/ProcessInboundMessageResponse.java deleted file mode 100644 index f120247..0000000 --- a/src/main/java/co/lettermint/models/api/ProcessInboundMessageResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProcessInboundMessageResponse { - @JsonProperty("data") - public Map data; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectAccessScope.java b/src/main/java/co/lettermint/models/api/ProjectAccessScope.java deleted file mode 100644 index 0e084a1..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectAccessScope.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class ProjectAccessScope { - public static final String ALL = "all"; - public static final String SELECTED = "selected"; - - private ProjectAccessScope() {} -} diff --git a/src/main/java/co/lettermint/models/api/ProjectCreatedData.java b/src/main/java/co/lettermint/models/api/ProjectCreatedData.java deleted file mode 100644 index 6b65672..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectCreatedData.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectCreatedData { - @JsonProperty("data") - public ProjectData data; - - @JsonProperty("message") - public String message; - - @JsonProperty("api_token") - public String apiToken; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectData.java b/src/main/java/co/lettermint/models/api/ProjectData.java deleted file mode 100644 index ee95fd5..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectData.java +++ /dev/null @@ -1,56 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectData { - @JsonProperty("id") - public String id; - - @JsonProperty("name") - public String name; - - @JsonProperty("smtp_enabled") - public Boolean smtpEnabled; - - @JsonProperty("redact_email_content") - public Boolean redactEmailContent; - - @JsonProperty("default_route_id") - public String defaultRouteId; - - @JsonProperty("token_generated_at") - public String tokenGeneratedAt; - - @JsonProperty("token_last_used_at") - public String tokenLastUsedAt; - - @JsonProperty("token_last_used_ip") - public String tokenLastUsedIp; - - @JsonProperty("routes") - public List routes; - - @JsonProperty("routes_count") - public Integer routesCount; - - @JsonProperty("domains") - public List domains; - - @JsonProperty("domains_count") - public Integer domainsCount; - - @JsonProperty("last_28_days") - public MessageStatsData last28Days; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; - - @JsonProperty("delivery_mode") - public String deliveryMode; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectDestroyResponse.java b/src/main/java/co/lettermint/models/api/ProjectDestroyResponse.java deleted file mode 100644 index 2fe51f3..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectDestroyResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectDestroyResponse { - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectIndexResponse.java b/src/main/java/co/lettermint/models/api/ProjectIndexResponse.java deleted file mode 100644 index 5f78c67..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectIndexResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectIndexResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectListData.java b/src/main/java/co/lettermint/models/api/ProjectListData.java deleted file mode 100644 index 1eecd24..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectListData.java +++ /dev/null @@ -1,34 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectListData { - @JsonProperty("id") - public String id; - - @JsonProperty("name") - public String name; - - @JsonProperty("delivery_mode") - public String deliveryMode; - - @JsonProperty("smtp_enabled") - public Boolean smtpEnabled; - - @JsonProperty("routes_count") - public Integer routesCount; - - @JsonProperty("domains_count") - public Integer domainsCount; - - @JsonProperty("last_28_days") - public MessageStatsData last28Days; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectRotateTokenResponse.java b/src/main/java/co/lettermint/models/api/ProjectRotateTokenResponse.java deleted file mode 100644 index 194f83d..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectRotateTokenResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectRotateTokenResponse { - @JsonProperty("data") - public ProjectData data; - - @JsonProperty("new_token") - public String newToken; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectStoreResponse.java b/src/main/java/co/lettermint/models/api/ProjectStoreResponse.java deleted file mode 100644 index 49e7ee5..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectStoreResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectStoreResponse { - @JsonProperty("data") - public ProjectData data; - - @JsonProperty("message") - public String message; - - @JsonProperty("api_token") - public String apiToken; -} diff --git a/src/main/java/co/lettermint/models/api/ProjectUpdateResponse.java b/src/main/java/co/lettermint/models/api/ProjectUpdateResponse.java deleted file mode 100644 index 3cfd82c..0000000 --- a/src/main/java/co/lettermint/models/api/ProjectUpdateResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ProjectUpdateResponse { - @JsonProperty("data") - public ProjectData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/RbacConflictCode.java b/src/main/java/co/lettermint/models/api/RbacConflictCode.java deleted file mode 100644 index 31ab13f..0000000 --- a/src/main/java/co/lettermint/models/api/RbacConflictCode.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.lettermint.models.api; - -public final class RbacConflictCode { - public static final String STALERESOURCE = "stale_resource"; - public static final String OWNERPROTECTED = "owner_protected"; - public static final String LASTOWNER = "last_owner"; - public static final String BUILTINROLEIMMUTABLE = "built_in_role_immutable"; - public static final String CUSTOMROLEREQUIRESPRO = "custom_role_requires_pro"; - - private RbacConflictCode() {} -} diff --git a/src/main/java/co/lettermint/models/api/RbacPermission.java b/src/main/java/co/lettermint/models/api/RbacPermission.java deleted file mode 100644 index a3ed6aa..0000000 --- a/src/main/java/co/lettermint/models/api/RbacPermission.java +++ /dev/null @@ -1,47 +0,0 @@ -package co.lettermint.models.api; - -public final class RbacPermission { - public static final String TEAMMANAGE = "team:manage"; - public static final String BILLINGMANAGE = "billing:manage"; - public static final String SECURITYMANAGE = "security:manage"; - public static final String AUDITREAD = "audit:read"; - public static final String SUPPORTMANAGE = "support:manage"; - public static final String MEMBERSREAD = "members:read"; - public static final String MEMBERSMANAGE = "members:manage"; - public static final String ROLESMANAGE = "roles:manage"; - public static final String TEAMTOKENSREAD = "team_tokens:read"; - public static final String TEAMTOKENSMANAGE = "team_tokens:manage"; - public static final String TEAMTOKENSROTATE = "team_tokens:rotate"; - public static final String TEAMTOKENSREVOKE = "team_tokens:revoke"; - public static final String PROJECTSCREATE = "projects:create"; - public static final String TEAMSUPPRESSIONSREAD = "team_suppressions:read"; - public static final String TEAMSUPPRESSIONSADD = "team_suppressions:add"; - public static final String TEAMSUPPRESSIONSREMOVE = "team_suppressions:remove"; - public static final String PROJECTSREAD = "projects:read"; - public static final String PROJECTSMANAGE = "projects:manage"; - public static final String PROJECTSDELETE = "projects:delete"; - public static final String ROUTESREAD = "routes:read"; - public static final String ROUTESMANAGE = "routes:manage"; - public static final String ROUTESDELETE = "routes:delete"; - public static final String DOMAINSREAD = "domains:read"; - public static final String DOMAINSMANAGE = "domains:manage"; - public static final String DOMAINSDELETE = "domains:delete"; - public static final String PROJECTTOKENSREAD = "project_tokens:read"; - public static final String PROJECTTOKENSMANAGE = "project_tokens:manage"; - public static final String PROJECTTOKENSROTATE = "project_tokens:rotate"; - public static final String PROJECTTOKENSREVOKE = "project_tokens:revoke"; - public static final String WEBHOOKSREAD = "webhooks:read"; - public static final String WEBHOOKSMANAGE = "webhooks:manage"; - public static final String WEBHOOKSDELETE = "webhooks:delete"; - public static final String WEBHOOKSROTATESECRET = "webhooks:rotate_secret"; - public static final String STATSREAD = "stats:read"; - public static final String ANALYTICSREAD = "analytics:read"; - public static final String MESSAGESREAD = "messages:read"; - public static final String MESSAGESREADCONTENT = "messages:read_content"; - public static final String MESSAGESSEND = "messages:send"; - public static final String SUPPRESSIONSREAD = "suppressions:read"; - public static final String SUPPRESSIONSADD = "suppressions:add"; - public static final String SUPPRESSIONSREMOVE = "suppressions:remove"; - - private RbacPermission() {} -} diff --git a/src/main/java/co/lettermint/models/api/RecordType.java b/src/main/java/co/lettermint/models/api/RecordType.java deleted file mode 100644 index 71fbd59..0000000 --- a/src/main/java/co/lettermint/models/api/RecordType.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class RecordType { - public static final String TXT = "TXT"; - public static final String CNAME = "CNAME"; - public static final String MX = "MX"; - - private RecordType() {} -} diff --git a/src/main/java/co/lettermint/models/api/ReportForwardingRequest.java b/src/main/java/co/lettermint/models/api/ReportForwardingRequest.java deleted file mode 100644 index 0e1a7f3..0000000 --- a/src/main/java/co/lettermint/models/api/ReportForwardingRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ReportForwardingRequest { - @JsonProperty("destination") - public String destination; -} diff --git a/src/main/java/co/lettermint/models/api/ReportForwardingResource.java b/src/main/java/co/lettermint/models/api/ReportForwardingResource.java deleted file mode 100644 index b3e1dc3..0000000 --- a/src/main/java/co/lettermint/models/api/ReportForwardingResource.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ReportForwardingResource { - @JsonProperty("destination") - public String destination; - - @JsonProperty("verified") - public Boolean verified; - - @JsonProperty("verified_at") - public String verifiedAt; -} diff --git a/src/main/java/co/lettermint/models/api/RescheduleMessageRequest.java b/src/main/java/co/lettermint/models/api/RescheduleMessageRequest.java deleted file mode 100644 index 45ebb24..0000000 --- a/src/main/java/co/lettermint/models/api/RescheduleMessageRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RescheduleMessageRequest { - @JsonProperty("scheduled_at") - public String scheduledAt; -} diff --git a/src/main/java/co/lettermint/models/api/RescheduleMessageResponse.java b/src/main/java/co/lettermint/models/api/RescheduleMessageResponse.java deleted file mode 100644 index f0add62..0000000 --- a/src/main/java/co/lettermint/models/api/RescheduleMessageResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RescheduleMessageResponse { - @JsonProperty("message_id") - public String messageId; - - @JsonProperty("status") - public String status; - - @JsonProperty("scheduled_at") - public String scheduledAt; -} diff --git a/src/main/java/co/lettermint/models/api/ResendReportForwardingCodeResponse.java b/src/main/java/co/lettermint/models/api/ResendReportForwardingCodeResponse.java deleted file mode 100644 index 1e55202..0000000 --- a/src/main/java/co/lettermint/models/api/ResendReportForwardingCodeResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class ResendReportForwardingCodeResponse { - @JsonProperty("data") - public ReportForwardingResource data; -} diff --git a/src/main/java/co/lettermint/models/api/RouteData.java b/src/main/java/co/lettermint/models/api/RouteData.java deleted file mode 100644 index 39861cc..0000000 --- a/src/main/java/co/lettermint/models/api/RouteData.java +++ /dev/null @@ -1,69 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteData { - @JsonProperty("id") - public String id; - - @JsonProperty("project_id") - public String projectId; - - @JsonProperty("slug") - public String slug; - - @JsonProperty("name") - public String name; - - @JsonProperty("route_type") - public String routeType; - - @JsonProperty("is_default") - public Boolean isDefault; - - @JsonProperty("inbound_address") - public String inboundAddress; - - @JsonProperty("inbound_mx_hostname") - public String inboundMxHostname; - - @JsonProperty("inbound_route_domain") - public String inboundRouteDomain; - - @JsonProperty("inbound_domain") - public String inboundDomain; - - @JsonProperty("inbound_domain_verified_at") - public String inboundDomainVerifiedAt; - - @JsonProperty("inbound_spam_threshold") - public Double inboundSpamThreshold; - - @JsonProperty("attachment_delivery") - public String attachmentDelivery; - - @JsonProperty("settings") - public Map settings; - - @JsonProperty("project") - public ProjectData project; - - @JsonProperty("webhooks_count") - public Integer webhooksCount; - - @JsonProperty("suppressed_recipients_count") - public Integer suppressedRecipientsCount; - - @JsonProperty("statistics") - public List statistics; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; -} diff --git a/src/main/java/co/lettermint/models/api/RouteDestroyResponse.java b/src/main/java/co/lettermint/models/api/RouteDestroyResponse.java deleted file mode 100644 index fc01f21..0000000 --- a/src/main/java/co/lettermint/models/api/RouteDestroyResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteDestroyResponse { - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/RouteIndexResponse.java b/src/main/java/co/lettermint/models/api/RouteIndexResponse.java deleted file mode 100644 index 3686eb9..0000000 --- a/src/main/java/co/lettermint/models/api/RouteIndexResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteIndexResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/RouteListData.java b/src/main/java/co/lettermint/models/api/RouteListData.java deleted file mode 100644 index 99f9627..0000000 --- a/src/main/java/co/lettermint/models/api/RouteListData.java +++ /dev/null @@ -1,34 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteListData { - @JsonProperty("id") - public String id; - - @JsonProperty("slug") - public String slug; - - @JsonProperty("name") - public String name; - - @JsonProperty("route_type") - public String routeType; - - @JsonProperty("is_default") - public Boolean isDefault; - - @JsonProperty("webhooks_count") - public Integer webhooksCount; - - @JsonProperty("suppressed_recipients_count") - public Integer suppressedRecipientsCount; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; -} diff --git a/src/main/java/co/lettermint/models/api/RouteStatisticData.java b/src/main/java/co/lettermint/models/api/RouteStatisticData.java deleted file mode 100644 index fcf1b4d..0000000 --- a/src/main/java/co/lettermint/models/api/RouteStatisticData.java +++ /dev/null @@ -1,49 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteStatisticData { - @JsonProperty("date") - public String date; - - @JsonProperty("sent_count") - public Integer sentCount; - - @JsonProperty("delivered_count") - public Integer deliveredCount; - - @JsonProperty("opened_count") - public Integer openedCount; - - @JsonProperty("clicked_count") - public Integer clickedCount; - - @JsonProperty("hard_bounce_count") - public Integer hardBounceCount; - - @JsonProperty("spam_complaint_count") - public Integer spamComplaintCount; - - @JsonProperty("inbound_received_count") - public Integer inboundReceivedCount; - - @JsonProperty("observed_opened_count") - public Integer observedOpenedCount; - - @JsonProperty("human_opened_count") - public Integer humanOpenedCount; - - @JsonProperty("privacy_opened_count") - public Integer privacyOpenedCount; - - @JsonProperty("effective_opened_count") - public Integer effectiveOpenedCount; - - @JsonProperty("machine_opened_count") - public Integer machineOpenedCount; - - @JsonProperty("machine_clicked_count") - public Integer machineClickedCount; -} diff --git a/src/main/java/co/lettermint/models/api/RouteStoreResponse.java b/src/main/java/co/lettermint/models/api/RouteStoreResponse.java deleted file mode 100644 index 7f54e50..0000000 --- a/src/main/java/co/lettermint/models/api/RouteStoreResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteStoreResponse { - @JsonProperty("data") - public RouteData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/RouteType.java b/src/main/java/co/lettermint/models/api/RouteType.java deleted file mode 100644 index 7ac0794..0000000 --- a/src/main/java/co/lettermint/models/api/RouteType.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class RouteType { - public static final String TRANSACTIONAL = "transactional"; - public static final String BROADCAST = "broadcast"; - public static final String INBOUND = "inbound"; - - private RouteType() {} -} diff --git a/src/main/java/co/lettermint/models/api/RouteUpdateResponse.java b/src/main/java/co/lettermint/models/api/RouteUpdateResponse.java deleted file mode 100644 index da29bed..0000000 --- a/src/main/java/co/lettermint/models/api/RouteUpdateResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteUpdateResponse { - @JsonProperty("data") - public RouteData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/RouteVerifyInboundDomainResponse.java b/src/main/java/co/lettermint/models/api/RouteVerifyInboundDomainResponse.java deleted file mode 100644 index 40bc44d..0000000 --- a/src/main/java/co/lettermint/models/api/RouteVerifyInboundDomainResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class RouteVerifyInboundDomainResponse { - @JsonProperty("data") - public Map data; -} diff --git a/src/main/java/co/lettermint/models/api/SandboxResult.java b/src/main/java/co/lettermint/models/api/SandboxResult.java deleted file mode 100644 index a75a163..0000000 --- a/src/main/java/co/lettermint/models/api/SandboxResult.java +++ /dev/null @@ -1,17 +0,0 @@ -package co.lettermint.models.api; - -public final class SandboxResult { - public static final String DELIVERED = "delivered"; - public static final String HARDBOUNCED = "hard_bounced"; - public static final String SOFTBOUNCED = "soft_bounced"; - public static final String DEFERRED = "deferred"; - public static final String FAILED = "failed"; - public static final String SUPPRESSED = "suppressed"; - public static final String SPAMCOMPLAINT = "spam_complaint"; - public static final String AUTOREPLIED = "auto_replied"; - public static final String OPENED = "opened"; - public static final String CLICKED = "clicked"; - public static final String UNSUBSCRIBED = "unsubscribed"; - - private SandboxResult() {} -} diff --git a/src/main/java/co/lettermint/models/api/SendMailRequest.java b/src/main/java/co/lettermint/models/api/SendMailRequest.java deleted file mode 100644 index e6980c3..0000000 --- a/src/main/java/co/lettermint/models/api/SendMailRequest.java +++ /dev/null @@ -1,60 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SendMailRequest { - @JsonProperty("route") - public String route; - - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public List to; - - @JsonProperty("cc") - public List cc; - - @JsonProperty("bcc") - public List bcc; - - @JsonProperty("reply_to") - public List replyTo; - - @JsonProperty("subject") - public String subject; - - @JsonProperty("scheduled_at") - public String scheduledAt; - - @JsonProperty("headers") - public Map headers; - - @JsonProperty("metadata") - public Map metadata; - - @JsonProperty("tag") - public String tag; - - @JsonProperty("tags") - public List> tags; - - @JsonProperty("settings") - public Map settings; - - @JsonProperty("html") - public String html; - - @JsonProperty("text") - public String text; - - @JsonProperty("attachments") - public List> attachments; - - @JsonProperty("sandbox_result") - public String sandboxResult; -} diff --git a/src/main/java/co/lettermint/models/api/SendMailResponse.java b/src/main/java/co/lettermint/models/api/SendMailResponse.java deleted file mode 100644 index 19196e2..0000000 --- a/src/main/java/co/lettermint/models/api/SendMailResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SendMailResponse { - @JsonProperty("message_id") - public String messageId; - - @JsonProperty("status") - public String status; - - @JsonProperty("sandbox") - public Boolean sandbox; - - @JsonProperty("sandbox_result") - public String sandboxResult; - - @JsonProperty("scheduled_at") - public String scheduledAt; -} diff --git a/src/main/java/co/lettermint/models/api/SpamSymbol.java b/src/main/java/co/lettermint/models/api/SpamSymbol.java deleted file mode 100644 index cd38051..0000000 --- a/src/main/java/co/lettermint/models/api/SpamSymbol.java +++ /dev/null @@ -1,20 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SpamSymbol { - @JsonProperty("name") - public String name; - - @JsonProperty("score") - public Double score; - - @JsonProperty("options") - public List options; - - @JsonProperty("description") - public String description; -} diff --git a/src/main/java/co/lettermint/models/api/StatsDailyData.java b/src/main/java/co/lettermint/models/api/StatsDailyData.java deleted file mode 100644 index 61c5a5c..0000000 --- a/src/main/java/co/lettermint/models/api/StatsDailyData.java +++ /dev/null @@ -1,55 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StatsDailyData { - @JsonProperty("date") - public String date; - - @JsonProperty("sent") - public Integer sent; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("hard_bounced") - public Integer hardBounced; - - @JsonProperty("spam_complaints") - public Integer spamComplaints; - - @JsonProperty("opened") - public Integer opened; - - @JsonProperty("clicked") - public Integer clicked; - - @JsonProperty("inbound") - public StatsInboundData inbound; - - @JsonProperty("transactional") - public StatsTypeData transactional; - - @JsonProperty("broadcast") - public StatsTypeData broadcast; - - @JsonProperty("observed_opened") - public Integer observedOpened; - - @JsonProperty("human_opened") - public Integer humanOpened; - - @JsonProperty("privacy_opened") - public Integer privacyOpened; - - @JsonProperty("effective_opened") - public Integer effectiveOpened; - - @JsonProperty("machine_opened") - public Integer machineOpened; - - @JsonProperty("machine_clicked") - public Integer machineClicked; -} diff --git a/src/main/java/co/lettermint/models/api/StatsData.java b/src/main/java/co/lettermint/models/api/StatsData.java deleted file mode 100644 index 539274f..0000000 --- a/src/main/java/co/lettermint/models/api/StatsData.java +++ /dev/null @@ -1,20 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StatsData { - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("totals") - public StatsTotalsData totals; - - @JsonProperty("daily") - public List daily; -} diff --git a/src/main/java/co/lettermint/models/api/StatsInboundData.java b/src/main/java/co/lettermint/models/api/StatsInboundData.java deleted file mode 100644 index 329a6f1..0000000 --- a/src/main/java/co/lettermint/models/api/StatsInboundData.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StatsInboundData { - @JsonProperty("received") - public Integer received; -} diff --git a/src/main/java/co/lettermint/models/api/StatsRequestData.java b/src/main/java/co/lettermint/models/api/StatsRequestData.java deleted file mode 100644 index aa2e25a..0000000 --- a/src/main/java/co/lettermint/models/api/StatsRequestData.java +++ /dev/null @@ -1,19 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StatsRequestData { - @JsonProperty("from") - public String fromValue; - - @JsonProperty("to") - public String to; - - @JsonProperty("project_id") - public String projectId; - - @JsonProperty("include_machine") - public Boolean includeMachine; -} diff --git a/src/main/java/co/lettermint/models/api/StatsTotalsData.java b/src/main/java/co/lettermint/models/api/StatsTotalsData.java deleted file mode 100644 index f281270..0000000 --- a/src/main/java/co/lettermint/models/api/StatsTotalsData.java +++ /dev/null @@ -1,52 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StatsTotalsData { - @JsonProperty("sent") - public Integer sent; - - @JsonProperty("delivered") - public Integer delivered; - - @JsonProperty("hard_bounced") - public Integer hardBounced; - - @JsonProperty("spam_complaints") - public Integer spamComplaints; - - @JsonProperty("opened") - public Integer opened; - - @JsonProperty("clicked") - public Integer clicked; - - @JsonProperty("inbound") - public StatsInboundData inbound; - - @JsonProperty("transactional") - public StatsTypeData transactional; - - @JsonProperty("broadcast") - public StatsTypeData broadcast; - - @JsonProperty("observed_opened") - public Integer observedOpened; - - @JsonProperty("human_opened") - public Integer humanOpened; - - @JsonProperty("privacy_opened") - public Integer privacyOpened; - - @JsonProperty("effective_opened") - public Integer effectiveOpened; - - @JsonProperty("machine_opened") - public Integer machineOpened; - - @JsonProperty("machine_clicked") - public Integer machineClicked; -} diff --git a/src/main/java/co/lettermint/models/api/StatsTypeData.java b/src/main/java/co/lettermint/models/api/StatsTypeData.java deleted file mode 100644 index f9899ce..0000000 --- a/src/main/java/co/lettermint/models/api/StatsTypeData.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StatsTypeData { - @JsonProperty("sent") - public Integer sent; - - @JsonProperty("hard_bounced") - public Integer hardBounced; - - @JsonProperty("spam_complaints") - public Integer spamComplaints; -} diff --git a/src/main/java/co/lettermint/models/api/StoreDomainData.java b/src/main/java/co/lettermint/models/api/StoreDomainData.java deleted file mode 100644 index 820db1a..0000000 --- a/src/main/java/co/lettermint/models/api/StoreDomainData.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StoreDomainData { - @JsonProperty("domain") - public String domain; -} diff --git a/src/main/java/co/lettermint/models/api/StoreProjectData.java b/src/main/java/co/lettermint/models/api/StoreProjectData.java deleted file mode 100644 index 2d05a43..0000000 --- a/src/main/java/co/lettermint/models/api/StoreProjectData.java +++ /dev/null @@ -1,25 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StoreProjectData { - @JsonProperty("name") - public String name; - - @JsonProperty("smtp_enabled") - public Boolean smtpEnabled; - - @JsonProperty("delivery_mode") - public String deliveryMode; - - @JsonProperty("initial_routes") - public String initialRoutes; - - @JsonProperty("short_token") - public Boolean shortToken; - - @JsonProperty("redact_email_content") - public Boolean redactEmailContent; -} diff --git a/src/main/java/co/lettermint/models/api/StoreRouteData.java b/src/main/java/co/lettermint/models/api/StoreRouteData.java deleted file mode 100644 index 0a98090..0000000 --- a/src/main/java/co/lettermint/models/api/StoreRouteData.java +++ /dev/null @@ -1,31 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StoreRouteData { - @JsonProperty("name") - public String name; - - @JsonProperty("route_type") - public String routeType; - - @JsonProperty("slug") - public String slug; - - @JsonProperty("settings") - public UpdateRouteSettingsData settings; - - @JsonProperty("inbound_settings") - public UpdateRouteInboundSettingsData inboundSettings; - - @JsonProperty("inbound_domain") - public String inboundDomain; - - @JsonProperty("inbound_spam_threshold") - public Double inboundSpamThreshold; - - @JsonProperty("attachment_delivery") - public String attachmentDelivery; -} diff --git a/src/main/java/co/lettermint/models/api/StoreSuppressionData.java b/src/main/java/co/lettermint/models/api/StoreSuppressionData.java deleted file mode 100644 index de4b5ce..0000000 --- a/src/main/java/co/lettermint/models/api/StoreSuppressionData.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StoreSuppressionData { - @JsonProperty("email") - public String email; - - @JsonProperty("emails") - public List emails; - - @JsonProperty("reason") - public String reason; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("project_id") - public String projectId; - - @JsonProperty("applies_to") - public String appliesTo; -} diff --git a/src/main/java/co/lettermint/models/api/StoreWebhookData.java b/src/main/java/co/lettermint/models/api/StoreWebhookData.java deleted file mode 100644 index 7f55574..0000000 --- a/src/main/java/co/lettermint/models/api/StoreWebhookData.java +++ /dev/null @@ -1,42 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class StoreWebhookData { - @JsonProperty("name") - public String name; - - @JsonProperty("url") - public String url; - - @com.fasterxml.jackson.annotation.JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL) - @JsonProperty("basic_auth") - public OptionalNullable basicAuth; - - @JsonProperty("events") - public List events; - - @JsonProperty("enabled") - public Boolean enabled; - - @JsonProperty("include_machine_events") - public Boolean includeMachineEvents; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("project_ids") - public List projectIds; - - @JsonProperty("route_ids") - public List routeIds; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("delivery_mode_filter") - public String deliveryModeFilter; -} diff --git a/src/main/java/co/lettermint/models/api/SuppressedRecipientData.java b/src/main/java/co/lettermint/models/api/SuppressedRecipientData.java deleted file mode 100644 index 5ed02d5..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressedRecipientData.java +++ /dev/null @@ -1,37 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SuppressedRecipientData { - @JsonProperty("id") - public String id; - - @JsonProperty("type") - public String type; - - @JsonProperty("value") - public String value; - - @JsonProperty("reason") - public String reason; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("applies_to") - public String appliesTo; - - @JsonProperty("project_id") - public String projectId; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("source_message") - public SuppressionSourceMessageData sourceMessage; - - @JsonProperty("created_at") - public String createdAt; -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionAppliesTo.java b/src/main/java/co/lettermint/models/api/SuppressionAppliesTo.java deleted file mode 100644 index 5502e54..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionAppliesTo.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class SuppressionAppliesTo { - public static final String ALL = "all"; - public static final String BROADCAST = "broadcast"; - - private SuppressionAppliesTo() {} -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionDestroyResponse.java b/src/main/java/co/lettermint/models/api/SuppressionDestroyResponse.java deleted file mode 100644 index 0573063..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionDestroyResponse.java +++ /dev/null @@ -1,22 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SuppressionDestroyResponse { - @JsonProperty("success") - public Boolean success; - - @JsonProperty("status") - public String status; - - @JsonProperty("message") - public String message; - - @JsonProperty("confidence") - public Double confidence; - - @JsonProperty("ticket_identifier") - public String ticketIdentifier; -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionIndexResponse.java b/src/main/java/co/lettermint/models/api/SuppressionIndexResponse.java deleted file mode 100644 index d8e2efb..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionIndexResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SuppressionIndexResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionReason.java b/src/main/java/co/lettermint/models/api/SuppressionReason.java deleted file mode 100644 index 6d3f1bb..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionReason.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -public final class SuppressionReason { - public static final String SPAMCOMPLAINT = "spam_complaint"; - public static final String HARDBOUNCE = "hard_bounce"; - public static final String UNSUBSCRIBE = "unsubscribe"; - public static final String MANUAL = "manual"; - - private SuppressionReason() {} -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionScope.java b/src/main/java/co/lettermint/models/api/SuppressionScope.java deleted file mode 100644 index dd20e96..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionScope.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class SuppressionScope { - public static final String TEAM = "team"; - public static final String PROJECT = "project"; - public static final String ROUTE = "route"; - - private SuppressionScope() {} -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionSourceMessageData.java b/src/main/java/co/lettermint/models/api/SuppressionSourceMessageData.java deleted file mode 100644 index 9ceb129..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionSourceMessageData.java +++ /dev/null @@ -1,19 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SuppressionSourceMessageData { - @JsonProperty("id") - public String id; - - @JsonProperty("available") - public Boolean available; - - @JsonProperty("subject") - public String subject; - - @JsonProperty("created_at") - public String createdAt; -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionStoreResponse.java b/src/main/java/co/lettermint/models/api/SuppressionStoreResponse.java deleted file mode 100644 index f6ae27a..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionStoreResponse.java +++ /dev/null @@ -1,14 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class SuppressionStoreResponse { - @JsonProperty("message") - public Object message; - - @JsonProperty("data") - public Map data; -} diff --git a/src/main/java/co/lettermint/models/api/SuppressionType.java b/src/main/java/co/lettermint/models/api/SuppressionType.java deleted file mode 100644 index 1071ea7..0000000 --- a/src/main/java/co/lettermint/models/api/SuppressionType.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class SuppressionType { - public static final String EMAIL = "email"; - public static final String DOMAIN = "domain"; - public static final String EXTENSION = "extension"; - - private SuppressionType() {} -} diff --git a/src/main/java/co/lettermint/models/api/TeamAddonData.java b/src/main/java/co/lettermint/models/api/TeamAddonData.java deleted file mode 100644 index 363b46e..0000000 --- a/src/main/java/co/lettermint/models/api/TeamAddonData.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamAddonData { - @JsonProperty("type") - public String type; - - @JsonProperty("expires_at") - public String expiresAt; -} diff --git a/src/main/java/co/lettermint/models/api/TeamData.java b/src/main/java/co/lettermint/models/api/TeamData.java deleted file mode 100644 index 4d8e178..0000000 --- a/src/main/java/co/lettermint/models/api/TeamData.java +++ /dev/null @@ -1,47 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamData { - @JsonProperty("id") - public String id; - - @JsonProperty("name") - public String name; - - @JsonProperty("type") - public String type; - - @JsonProperty("plan") - public String plan; - - @JsonProperty("included_volume") - public Integer includedVolume; - - @JsonProperty("tier") - public Integer tier; - - @JsonProperty("verified_at") - public String verifiedAt; - - @JsonProperty("features") - public List features; - - @JsonProperty("addons") - public List addons; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("domains_count") - public Integer domainsCount; - - @JsonProperty("projects_count") - public Integer projectsCount; - - @JsonProperty("members_count") - public Integer membersCount; -} diff --git a/src/main/java/co/lettermint/models/api/TeamMemberData.java b/src/main/java/co/lettermint/models/api/TeamMemberData.java deleted file mode 100644 index 4a9dfbc..0000000 --- a/src/main/java/co/lettermint/models/api/TeamMemberData.java +++ /dev/null @@ -1,26 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamMemberData { - @JsonProperty("id") - public String id; - - @JsonProperty("name") - public String name; - - @JsonProperty("email") - public String email; - - @JsonProperty("role") - public Map role; - - @JsonProperty("project_access") - public TeamMemberProjectAccessData projectAccess; - - @JsonProperty("joined_at") - public String joinedAt; -} diff --git a/src/main/java/co/lettermint/models/api/TeamMemberProjectAccessData.java b/src/main/java/co/lettermint/models/api/TeamMemberProjectAccessData.java deleted file mode 100644 index 7a70a15..0000000 --- a/src/main/java/co/lettermint/models/api/TeamMemberProjectAccessData.java +++ /dev/null @@ -1,15 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamMemberProjectAccessData { - @JsonProperty("scope") - public String scope; - - @JsonProperty("projects") - public List> projects; -} diff --git a/src/main/java/co/lettermint/models/api/TeamMembersResponse.java b/src/main/java/co/lettermint/models/api/TeamMembersResponse.java deleted file mode 100644 index 47221a0..0000000 --- a/src/main/java/co/lettermint/models/api/TeamMembersResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamMembersResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/TeamRoleData.java b/src/main/java/co/lettermint/models/api/TeamRoleData.java deleted file mode 100644 index 4ac46f2..0000000 --- a/src/main/java/co/lettermint/models/api/TeamRoleData.java +++ /dev/null @@ -1,23 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamRoleData { - @JsonProperty("id") - public String id; - - @JsonProperty("name") - public String name; - - @JsonProperty("system_key") - public String systemKey; - - @JsonProperty("permissions") - public List permissions; - - @JsonProperty("assignable") - public Boolean assignable; -} diff --git a/src/main/java/co/lettermint/models/api/TeamRolesResponse.java b/src/main/java/co/lettermint/models/api/TeamRolesResponse.java deleted file mode 100644 index 958eae0..0000000 --- a/src/main/java/co/lettermint/models/api/TeamRolesResponse.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamRolesResponse { - @JsonProperty("data") - public List data; -} diff --git a/src/main/java/co/lettermint/models/api/TeamType.java b/src/main/java/co/lettermint/models/api/TeamType.java deleted file mode 100644 index a737bfc..0000000 --- a/src/main/java/co/lettermint/models/api/TeamType.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class TeamType { - public static final String PERSONAL = "personal"; - public static final String BUSINESS = "business"; - - private TeamType() {} -} diff --git a/src/main/java/co/lettermint/models/api/TeamUpdateResponse.java b/src/main/java/co/lettermint/models/api/TeamUpdateResponse.java deleted file mode 100644 index 9a8331c..0000000 --- a/src/main/java/co/lettermint/models/api/TeamUpdateResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamUpdateResponse { - @JsonProperty("data") - public TeamData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/TeamUsageDetailData.java b/src/main/java/co/lettermint/models/api/TeamUsageDetailData.java deleted file mode 100644 index 85ff33f..0000000 --- a/src/main/java/co/lettermint/models/api/TeamUsageDetailData.java +++ /dev/null @@ -1,14 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamUsageDetailData { - @JsonProperty("current_period") - public TeamUsagePeriodData currentPeriod; - - @JsonProperty("historical_usage") - public List historicalUsage; -} diff --git a/src/main/java/co/lettermint/models/api/TeamUsagePeriodData.java b/src/main/java/co/lettermint/models/api/TeamUsagePeriodData.java deleted file mode 100644 index 121cd26..0000000 --- a/src/main/java/co/lettermint/models/api/TeamUsagePeriodData.java +++ /dev/null @@ -1,19 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class TeamUsagePeriodData { - @JsonProperty("usage") - public Integer usage; - - @JsonProperty("last_incremented_at") - public String lastIncrementedAt; - - @JsonProperty("period_start") - public String periodStart; - - @JsonProperty("period_end") - public String periodEnd; -} diff --git a/src/main/java/co/lettermint/models/api/TlsPolicy.java b/src/main/java/co/lettermint/models/api/TlsPolicy.java deleted file mode 100644 index f99ef38..0000000 --- a/src/main/java/co/lettermint/models/api/TlsPolicy.java +++ /dev/null @@ -1,8 +0,0 @@ -package co.lettermint.models.api; - -public final class TlsPolicy { - public static final String OPPORTUNISTIC = "opportunistic"; - public static final String ENFORCED = "enforced"; - - private TlsPolicy() {} -} diff --git a/src/main/java/co/lettermint/models/api/UpdateDomainProjectsData.java b/src/main/java/co/lettermint/models/api/UpdateDomainProjectsData.java deleted file mode 100644 index 9e3c1b6..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateDomainProjectsData.java +++ /dev/null @@ -1,11 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateDomainProjectsData { - @JsonProperty("project_ids") - public List projectIds; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateProjectData.java b/src/main/java/co/lettermint/models/api/UpdateProjectData.java deleted file mode 100644 index e6a14f0..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateProjectData.java +++ /dev/null @@ -1,22 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateProjectData { - @JsonProperty("name") - public String name; - - @JsonProperty("smtp_enabled") - public Boolean smtpEnabled; - - @JsonProperty("redact_email_content") - public Boolean redactEmailContent; - - @JsonProperty("default_route_id") - public String defaultRouteId; - - @JsonProperty("delivery_mode") - public String deliveryMode; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateReportForwardingRequest.java b/src/main/java/co/lettermint/models/api/UpdateReportForwardingRequest.java deleted file mode 100644 index 987c199..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateReportForwardingRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateReportForwardingRequest { - @JsonProperty("destination") - public String destination; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateReportForwardingResponse.java b/src/main/java/co/lettermint/models/api/UpdateReportForwardingResponse.java deleted file mode 100644 index 7876d1c..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateReportForwardingResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateReportForwardingResponse { - @JsonProperty("data") - public ReportForwardingResource data; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateRouteData.java b/src/main/java/co/lettermint/models/api/UpdateRouteData.java deleted file mode 100644 index cbb8a33..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateRouteData.java +++ /dev/null @@ -1,25 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateRouteData { - @JsonProperty("name") - public String name; - - @JsonProperty("settings") - public UpdateRouteSettingsData settings; - - @JsonProperty("inbound_settings") - public UpdateRouteInboundSettingsData inboundSettings; - - @JsonProperty("inbound_domain") - public String inboundDomain; - - @JsonProperty("inbound_spam_threshold") - public Double inboundSpamThreshold; - - @JsonProperty("attachment_delivery") - public String attachmentDelivery; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateRouteInboundSettingsData.java b/src/main/java/co/lettermint/models/api/UpdateRouteInboundSettingsData.java deleted file mode 100644 index 96a51a8..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateRouteInboundSettingsData.java +++ /dev/null @@ -1,16 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateRouteInboundSettingsData { - @JsonProperty("inbound_domain") - public String inboundDomain; - - @JsonProperty("inbound_spam_threshold") - public Double inboundSpamThreshold; - - @JsonProperty("attachment_delivery") - public String attachmentDelivery; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateRouteSettingsData.java b/src/main/java/co/lettermint/models/api/UpdateRouteSettingsData.java deleted file mode 100644 index b7c98fa..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateRouteSettingsData.java +++ /dev/null @@ -1,31 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateRouteSettingsData { - @JsonProperty("track_opens") - public Boolean trackOpens; - - @JsonProperty("track_clicks") - public Boolean trackClicks; - - @JsonProperty("generate_plaintext_fallback") - public Boolean generatePlaintextFallback; - - @JsonProperty("suppress_auto_responders") - public Boolean suppressAutoResponders; - - @JsonProperty("suppress_disposable_recipients") - public Boolean suppressDisposableRecipients; - - @JsonProperty("tls") - public String tls; - - @JsonProperty("disable_hosted_unsubscribe") - public Boolean disableHostedUnsubscribe; - - @JsonProperty("redact_email_content") - public Boolean redactEmailContent; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateTeamData.java b/src/main/java/co/lettermint/models/api/UpdateTeamData.java deleted file mode 100644 index d1d7a3c..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateTeamData.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateTeamData { - @JsonProperty("name") - public String name; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateTeamMemberAssignmentData.java b/src/main/java/co/lettermint/models/api/UpdateTeamMemberAssignmentData.java deleted file mode 100644 index 47d131e..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateTeamMemberAssignmentData.java +++ /dev/null @@ -1,14 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.Map; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateTeamMemberAssignmentData { - @JsonProperty("role_id") - public String roleId; - - @JsonProperty("project_access") - public Map projectAccess; -} diff --git a/src/main/java/co/lettermint/models/api/UpdateWebhookData.java b/src/main/java/co/lettermint/models/api/UpdateWebhookData.java deleted file mode 100644 index 81bf33b..0000000 --- a/src/main/java/co/lettermint/models/api/UpdateWebhookData.java +++ /dev/null @@ -1,42 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class UpdateWebhookData { - @JsonProperty("name") - public String name; - - @JsonProperty("url") - public String url; - - @com.fasterxml.jackson.annotation.JsonInclude(com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL) - @JsonProperty("basic_auth") - public OptionalNullable basicAuth; - - @JsonProperty("events") - public List events; - - @JsonProperty("enabled") - public Boolean enabled; - - @JsonProperty("include_machine_events") - public Boolean includeMachineEvents; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("project_ids") - public List projectIds; - - @JsonProperty("route_ids") - public List routeIds; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("delivery_mode_filter") - public String deliveryModeFilter; -} diff --git a/src/main/java/co/lettermint/models/api/VerifyReportForwardingRequest.java b/src/main/java/co/lettermint/models/api/VerifyReportForwardingRequest.java deleted file mode 100644 index 79bb669..0000000 --- a/src/main/java/co/lettermint/models/api/VerifyReportForwardingRequest.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class VerifyReportForwardingRequest { - @JsonProperty("code") - public String code; -} diff --git a/src/main/java/co/lettermint/models/api/VerifyReportForwardingResponse.java b/src/main/java/co/lettermint/models/api/VerifyReportForwardingResponse.java deleted file mode 100644 index cfcd6a4..0000000 --- a/src/main/java/co/lettermint/models/api/VerifyReportForwardingResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class VerifyReportForwardingResponse { - @JsonProperty("data") - public ReportForwardingResource data; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookBasicAuthData.java b/src/main/java/co/lettermint/models/api/WebhookBasicAuthData.java deleted file mode 100644 index 6b8ea6c..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookBasicAuthData.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookBasicAuthData { - @JsonProperty("username") - public String username; - - @JsonProperty("password") - public String password; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookData.java b/src/main/java/co/lettermint/models/api/WebhookData.java deleted file mode 100644 index 45c54af..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookData.java +++ /dev/null @@ -1,53 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookData { - @JsonProperty("id") - public String id; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("project_ids") - public List projectIds; - - @JsonProperty("route_ids") - public List routeIds; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("name") - public String name; - - @JsonProperty("url") - public String url; - - @JsonProperty("has_basic_auth") - public boolean hasBasicAuth; - - @JsonProperty("events") - public List events; - - @JsonProperty("enabled") - public Boolean enabled; - - @JsonProperty("include_machine_events") - public Boolean includeMachineEvents; - - @JsonProperty("last_called_at") - public String lastCalledAt; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; - - @JsonProperty("delivery_mode_filter") - public String deliveryModeFilter; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookDeliveriesResponse.java b/src/main/java/co/lettermint/models/api/WebhookDeliveriesResponse.java deleted file mode 100644 index b9dadd7..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookDeliveriesResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookDeliveriesResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookDeliveryData.java b/src/main/java/co/lettermint/models/api/WebhookDeliveryData.java deleted file mode 100644 index cda4b85..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookDeliveryData.java +++ /dev/null @@ -1,59 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookDeliveryData { - @JsonProperty("id") - public String id; - - @JsonProperty("webhook_id") - public String webhookId; - - @JsonProperty("event_type") - public String eventType; - - @JsonProperty("source_scope") - public String sourceScope; - - @JsonProperty("source_project_id") - public String sourceProjectId; - - @JsonProperty("source_route_id") - public String sourceRouteId; - - @JsonProperty("status") - public String status; - - @JsonProperty("attempt_number") - public Integer attemptNumber; - - @JsonProperty("http_status_code") - public Integer httpStatusCode; - - @JsonProperty("duration_ms") - public Integer durationMs; - - @JsonProperty("payload") - public List payload; - - @JsonProperty("response_body") - public String responseBody; - - @JsonProperty("response_headers") - public List responseHeaders; - - @JsonProperty("error_message") - public String errorMessage; - - @JsonProperty("delivered_at") - public String deliveredAt; - - @JsonProperty("timestamp") - public String timestamp; - - @JsonProperty("sandbox") - public Boolean sandbox; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookDeliveryListData.java b/src/main/java/co/lettermint/models/api/WebhookDeliveryListData.java deleted file mode 100644 index 02dcc0a..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookDeliveryListData.java +++ /dev/null @@ -1,46 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookDeliveryListData { - @JsonProperty("id") - public String id; - - @JsonProperty("webhook_id") - public String webhookId; - - @JsonProperty("event_type") - public String eventType; - - @JsonProperty("source_scope") - public String sourceScope; - - @JsonProperty("source_project_id") - public String sourceProjectId; - - @JsonProperty("source_route_id") - public String sourceRouteId; - - @JsonProperty("status") - public String status; - - @JsonProperty("sandbox") - public Boolean sandbox; - - @JsonProperty("attempt_number") - public Integer attemptNumber; - - @JsonProperty("http_status_code") - public Integer httpStatusCode; - - @JsonProperty("duration_ms") - public Integer durationMs; - - @JsonProperty("delivered_at") - public String deliveredAt; - - @JsonProperty("created_at") - public String createdAt; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookDeliveryModeFilter.java b/src/main/java/co/lettermint/models/api/WebhookDeliveryModeFilter.java deleted file mode 100644 index fda23a3..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookDeliveryModeFilter.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class WebhookDeliveryModeFilter { - public static final String LIVE = "live"; - public static final String SANDBOX = "sandbox"; - public static final String BOTH = "both"; - - private WebhookDeliveryModeFilter() {} -} diff --git a/src/main/java/co/lettermint/models/api/WebhookDeliveryStatus.java b/src/main/java/co/lettermint/models/api/WebhookDeliveryStatus.java deleted file mode 100644 index c7d45a5..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookDeliveryStatus.java +++ /dev/null @@ -1,12 +0,0 @@ -package co.lettermint.models.api; - -public final class WebhookDeliveryStatus { - public static final String PENDING = "pending"; - public static final String SUCCESS = "success"; - public static final String FAILED = "failed"; - public static final String CLIENTERROR = "client_error"; - public static final String SERVERERROR = "server_error"; - public static final String TIMEOUT = "timeout"; - - private WebhookDeliveryStatus() {} -} diff --git a/src/main/java/co/lettermint/models/api/WebhookDestroyResponse.java b/src/main/java/co/lettermint/models/api/WebhookDestroyResponse.java deleted file mode 100644 index 5c32b9a..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookDestroyResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookDestroyResponse { - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookEvent.java b/src/main/java/co/lettermint/models/api/WebhookEvent.java deleted file mode 100644 index 46fe0a4..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookEvent.java +++ /dev/null @@ -1,27 +0,0 @@ -package co.lettermint.models.api; - -public final class WebhookEvent { - public static final String MESSAGECREATED = "message.created"; - public static final String MESSAGESENT = "message.sent"; - public static final String MESSAGEDELIVERED = "message.delivered"; - public static final String MESSAGEAUTOREPLIED = "message.auto_replied"; - public static final String MESSAGEHARDBOUNCED = "message.hard_bounced"; - public static final String MESSAGESOFTBOUNCED = "message.soft_bounced"; - public static final String MESSAGESPAMCOMPLAINT = "message.spam_complaint"; - public static final String MESSAGEFAILED = "message.failed"; - public static final String MESSAGESUPPRESSED = "message.suppressed"; - public static final String MESSAGEUNSUBSCRIBED = "message.unsubscribed"; - public static final String MESSAGEOPENED = "message.opened"; - public static final String MESSAGECLICKED = "message.clicked"; - public static final String MESSAGEINBOUND = "message.inbound"; - public static final String MESSAGEPOLICYREJECTED = "message.policy_rejected"; - public static final String MESSAGESCHEDULED = "message.scheduled"; - public static final String MESSAGERESCHEDULED = "message.rescheduled"; - public static final String MESSAGECANCELED = "message.canceled"; - public static final String MESSAGERELEASED = "message.released"; - public static final String SUPPRESSIONADDED = "suppression.added"; - public static final String SUPPRESSIONREMOVED = "suppression.removed"; - public static final String WEBHOOKTEST = "webhook.test"; - - private WebhookEvent() {} -} diff --git a/src/main/java/co/lettermint/models/api/WebhookIndexResponse.java b/src/main/java/co/lettermint/models/api/WebhookIndexResponse.java deleted file mode 100644 index 4dd3377..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookIndexResponse.java +++ /dev/null @@ -1,29 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookIndexResponse { - @JsonProperty("data") - public List data; - - @JsonProperty("path") - public String path; - - @JsonProperty("per_page") - public Integer perPage; - - @JsonProperty("next_cursor") - public String nextCursor; - - @JsonProperty("next_page_url") - public String nextPageUrl; - - @JsonProperty("prev_cursor") - public String prevCursor; - - @JsonProperty("prev_page_url") - public String prevPageUrl; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookListData.java b/src/main/java/co/lettermint/models/api/WebhookListData.java deleted file mode 100644 index 9c9c37b..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookListData.java +++ /dev/null @@ -1,50 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookListData { - @JsonProperty("id") - public String id; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("project_ids") - public List projectIds; - - @JsonProperty("route_ids") - public List routeIds; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("name") - public String name; - - @JsonProperty("url") - public String url; - - @JsonProperty("has_basic_auth") - public boolean hasBasicAuth; - - @JsonProperty("events") - public List events; - - @JsonProperty("enabled") - public Boolean enabled; - - @JsonProperty("delivery_mode_filter") - public String deliveryModeFilter; - - @JsonProperty("last_called_at") - public String lastCalledAt; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookRegenerateSecretResponse.java b/src/main/java/co/lettermint/models/api/WebhookRegenerateSecretResponse.java deleted file mode 100644 index da5ffef..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookRegenerateSecretResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookRegenerateSecretResponse { - @JsonProperty("data") - public WebhookSecretData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookScope.java b/src/main/java/co/lettermint/models/api/WebhookScope.java deleted file mode 100644 index 8122fc0..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookScope.java +++ /dev/null @@ -1,9 +0,0 @@ -package co.lettermint.models.api; - -public final class WebhookScope { - public static final String TEAM = "team"; - public static final String PROJECT = "project"; - public static final String ROUTE = "route"; - - private WebhookScope() {} -} diff --git a/src/main/java/co/lettermint/models/api/WebhookSecretData.java b/src/main/java/co/lettermint/models/api/WebhookSecretData.java deleted file mode 100644 index 85d2793..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookSecretData.java +++ /dev/null @@ -1,56 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookSecretData { - @JsonProperty("id") - public String id; - - @JsonProperty("scope") - public String scope; - - @JsonProperty("project_ids") - public List projectIds; - - @JsonProperty("route_ids") - public List routeIds; - - @JsonProperty("route_id") - public String routeId; - - @JsonProperty("name") - public String name; - - @JsonProperty("url") - public String url; - - @JsonProperty("has_basic_auth") - public boolean hasBasicAuth; - - @JsonProperty("events") - public List events; - - @JsonProperty("enabled") - public Boolean enabled; - - @JsonProperty("include_machine_events") - public Boolean includeMachineEvents; - - @JsonProperty("secret") - public String secret; - - @JsonProperty("last_called_at") - public String lastCalledAt; - - @JsonProperty("created_at") - public String createdAt; - - @JsonProperty("updated_at") - public String updatedAt; - - @JsonProperty("delivery_mode_filter") - public String deliveryModeFilter; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookStoreResponse.java b/src/main/java/co/lettermint/models/api/WebhookStoreResponse.java deleted file mode 100644 index 2e0c2e3..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookStoreResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookStoreResponse { - @JsonProperty("data") - public WebhookSecretData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookTestResponse.java b/src/main/java/co/lettermint/models/api/WebhookTestResponse.java deleted file mode 100644 index 2853bbf..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookTestResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookTestResponse { - @JsonProperty("message") - public String message; - - @JsonProperty("delivery_id") - public String deliveryId; -} diff --git a/src/main/java/co/lettermint/models/api/WebhookUpdateResponse.java b/src/main/java/co/lettermint/models/api/WebhookUpdateResponse.java deleted file mode 100644 index fb78010..0000000 --- a/src/main/java/co/lettermint/models/api/WebhookUpdateResponse.java +++ /dev/null @@ -1,13 +0,0 @@ -package co.lettermint.models.api; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class WebhookUpdateResponse { - @JsonProperty("data") - public WebhookData data; - - @JsonProperty("message") - public String message; -} diff --git a/src/main/java/co/lettermint/webhooks/Webhook.java b/src/main/java/co/lettermint/webhooks/Webhook.java deleted file mode 100644 index 7c41cca..0000000 --- a/src/main/java/co/lettermint/webhooks/Webhook.java +++ /dev/null @@ -1,208 +0,0 @@ -package co.lettermint.webhooks; - -import co.lettermint.exceptions.webhook.InvalidSignatureException; -import co.lettermint.exceptions.webhook.TimestampToleranceException; -import co.lettermint.exceptions.webhook.WebhookVerificationException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; -import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.util.Map; - -/** - * Utility class for verifying Lettermint webhook signatures. - */ -public class Webhook { - - private static final String HMAC_SHA256 = "HmacSHA256"; - private static final int DEFAULT_TOLERANCE_SECONDS = 300; - private static final ObjectMapper objectMapper = new ObjectMapper(); - - private Webhook() { - } - - /** - * Verify a webhook signature and parse the payload. - * - * @param payload The raw JSON payload string - * @param signature The signature header value (format: "t={timestamp},v1={hash}") - * @param secret The webhook signing secret - * @return The parsed payload as a Map - * @throws WebhookVerificationException if verification fails - */ - public static Map verify(String payload, String signature, String secret) { - return verify(payload, signature, secret, DEFAULT_TOLERANCE_SECONDS); - } - - /** - * Verify a webhook signature and parse the payload. - * - * @param payload The raw JSON payload string - * @param signature The signature header value (format: "t={timestamp},v1={hash}") - * @param secret The webhook signing secret - * @param tolerance Maximum allowed difference in seconds between the signature timestamp and the - * current time, in either direction (0 to disable timestamp check) - * @return The parsed payload as a Map - * @throws WebhookVerificationException if verification fails - */ - public static Map verify(String payload, String signature, String secret, int tolerance) { - if (payload == null || payload.isEmpty()) { - throw new WebhookVerificationException("Payload is required"); - } - if (signature == null || signature.isEmpty()) { - throw new WebhookVerificationException("Signature is required"); - } - if (secret == null || secret.isEmpty()) { - throw new WebhookVerificationException("Secret is required"); - } - - SignatureParts parts = parseSignature(signature); - verifyTimestamp(parts.timestamp, tolerance); - verifySignature(payload, parts, secret); - - return parsePayload(payload); - } - - private static SignatureParts parseSignature(String signature) { - String timestamp = null; - String hash = null; - - for (String part : signature.split(",")) { - String[] keyValue = part.split("=", 2); - if (keyValue.length != 2) { - continue; - } - - String key = keyValue[0].trim(); - String value = keyValue[1].trim(); - - if ("t".equals(key)) { - timestamp = value; - } else if ("v1".equals(key)) { - hash = value; - } - } - - if (timestamp == null || timestamp.isEmpty()) { - throw new WebhookVerificationException("Missing timestamp in signature"); - } - if (hash == null || hash.isEmpty()) { - throw new WebhookVerificationException("Missing hash in signature"); - } - - return new SignatureParts(timestamp, hash); - } - - private static void verifyTimestamp(String timestampStr, int tolerance) { - if (tolerance <= 0) { - return; - } - - long timestamp; - try { - timestamp = Long.parseLong(timestampStr); - } catch (NumberFormatException e) { - throw new WebhookVerificationException("Invalid timestamp format: " + timestampStr); - } - - long now = System.currentTimeMillis() / 1000; - - // Accept timestamps within the tolerance window in both directions so that - // small clock skew between sender and receiver does not break verification. - long age = now - timestamp; - if (age > tolerance) { - throw new TimestampToleranceException( - String.format("Timestamp too old. Timestamp: %d, Current: %d, Age: %d seconds, Tolerance: %d seconds", - timestamp, now, age, tolerance), - timestamp, - tolerance - ); - } - if (-age > tolerance) { - throw new TimestampToleranceException( - String.format("Timestamp too far in the future. Timestamp: %d, Current: %d, Ahead: %d seconds, Tolerance: %d seconds", - timestamp, now, -age, tolerance), - timestamp, - tolerance - ); - } - } - - private static void verifySignature(String payload, SignatureParts parts, String secret) { - String signedPayload = parts.timestamp + "." + payload; - String expectedHash = computeHmacSha256(signedPayload, secret); - - if (!secureCompare(expectedHash, parts.hash)) { - throw new InvalidSignatureException("Signature verification failed"); - } - } - - private static String computeHmacSha256(String data, String secret) { - try { - Mac mac = Mac.getInstance(HMAC_SHA256); - SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), HMAC_SHA256); - mac.init(secretKeySpec); - byte[] hmacBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); - return bytesToHex(hmacBytes); - } catch (NoSuchAlgorithmException | InvalidKeyException e) { - throw new WebhookVerificationException("Failed to compute HMAC", e); - } - } - - private static String bytesToHex(byte[] bytes) { - StringBuilder hexString = new StringBuilder(); - for (byte b : bytes) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - return hexString.toString(); - } - - /** - * Constant-time string comparison to prevent timing attacks. - */ - private static boolean secureCompare(String a, String b) { - if (a == null || b == null) { - return false; - } - - byte[] aBytes = a.getBytes(StandardCharsets.UTF_8); - byte[] bBytes = b.getBytes(StandardCharsets.UTF_8); - - if (aBytes.length != bBytes.length) { - return false; - } - - int result = 0; - for (int i = 0; i < aBytes.length; i++) { - result |= aBytes[i] ^ bBytes[i]; - } - return result == 0; - } - - private static Map parsePayload(String payload) { - try { - return objectMapper.readValue(payload, new TypeReference>() { - }); - } catch (Exception e) { - throw new WebhookVerificationException("Failed to parse payload JSON", e); - } - } - - private static class SignatureParts { - final String timestamp; - final String hash; - - SignatureParts(String timestamp, String hash) { - this.timestamp = timestamp; - this.hash = hash; - } - } -} diff --git a/src/test/java/co/lettermint/AnalyticsForwardingTest.java b/src/test/java/co/lettermint/AnalyticsForwardingTest.java deleted file mode 100644 index 8e5dea2..0000000 --- a/src/test/java/co/lettermint/AnalyticsForwardingTest.java +++ /dev/null @@ -1,61 +0,0 @@ -package co.lettermint; - -import co.lettermint.api.ApiClient; -import co.lettermint.models.api.*; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.jupiter.api.Test; -import java.util.Arrays; -import static org.junit.jupiter.api.Assertions.*; - -class AnalyticsForwardingTest { - @Test - void analyticsAndForwardingUseTheirWireContracts() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse().setBody("{\"data\":{\"summary\":{}},\"meta\":{\"timezone\":\"UTC\"},\"pagination\":{\"total_groups\":0,\"returned_groups\":0,\"next_cursor\":null,\"truncated\":false}}")); - for (int i=0; i<4; i++) server.enqueue(new MockResponse().setBody("{\"data\":{\"destination\":null,\"verified\":false,\"verified_at\":null}}")); - server.enqueue(new MockResponse().setResponseCode(204)); - server.start(); - ApiClient api = Lettermint.api("team-token", server.url("/v1").toString()); - AnalyticsRequest payload = new AnalyticsRequest(); - payload.metrics = Arrays.asList("accepted", "delivered"); - payload.include = Arrays.asList("summary"); - assertEquals("UTC", api.analytics(payload).meta.timezone); - assertNull(api.projects().retrieveReportForwarding("project/id").data.destination); - ReportForwardingRequest destination = new ReportForwardingRequest(); - destination.destination = "reports@example.com"; - api.projects().updateReportForwarding("project/id", destination); - VerifyReportForwardingRequest code = new VerifyReportForwardingRequest(); - code.code = "123456"; - api.projects().verifyReportForwarding("project/id", code); - api.projects().resendReportForwardingCode("project/id"); - api.projects().deleteReportForwarding("project/id"); - String base = "/v1/projects/project%2Fid/report-forwarding"; - String[] paths = {"/v1/analytics", base, base, base+"/verify", base+"/resend-code", base}; - String[] methods = {"POST", "GET", "PUT", "POST", "POST", "DELETE"}; - ObjectMapper mapper = new ObjectMapper(); - for (int i=0; i<6; i++) { - RecordedRequest request = server.takeRequest(); - assertEquals(paths[i], request.getPath()); - assertEquals(methods[i], request.getMethod()); - assertEquals("Bearer team-token", request.getHeader("Authorization")); - assertNull(request.getHeader("x-lettermint-token")); - if (i==0) assertEquals("accepted", mapper.readTree(request.getBody().readUtf8()).get("metrics").get(0).asText()); - if (i==2) assertEquals("reports@example.com", mapper.readTree(request.getBody().readUtf8()).get("destination").asText()); - if (i==3) assertEquals("123456", mapper.readTree(request.getBody().readUtf8()).get("code").asText()); - } - } - } - - @Test - void updatedResponseFieldsRemainAvailable() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - ProjectStoreResponse created = mapper.readValue("{\"data\":{},\"message\":\"Created\",\"api_token\":\"project-token\"}", ProjectStoreResponse.class); - assertEquals("project-token", created.apiToken); - SuppressionDestroyResponse review = mapper.readValue("{\"success\":true,\"status\":\"review_ticket_exists\",\"message\":\"Review\",\"ticket_identifier\":\"ticket-1\",\"confidence\":0.9}", SuppressionDestroyResponse.class); - assertEquals("ticket-1", review.ticketIdentifier); - assertEquals(0.9, review.confidence); - } -} diff --git a/src/test/java/co/lettermint/ApiClientTest.java b/src/test/java/co/lettermint/ApiClientTest.java deleted file mode 100644 index 19ec567..0000000 --- a/src/test/java/co/lettermint/ApiClientTest.java +++ /dev/null @@ -1,356 +0,0 @@ -package co.lettermint; - -import co.lettermint.api.ApiClient; -import co.lettermint.models.api.SendMailRequest; -import co.lettermint.models.api.SendMailResponse; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.jupiter.api.Test; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -class ApiClientTest { - - @Test - void staticEmailUsesSendingTokenAndRawPing() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse().setBody("pong\n")); - server.start(); - - String pong = Lettermint.email("sending-token", server.url("/v1").toString()).ping(); - - RecordedRequest request = server.takeRequest(); - assertEquals("/v1/ping", request.getPath()); - assertEquals("sending-token", request.getHeader("x-lettermint-token")); - assertNull(request.getHeader("Authorization")); - assertEquals("pong", pong); - } - } - - @Test - void staticApiUsesBearerTokenAndRawPing() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse().setBody("pong\n")); - server.start(); - - ApiClient api = Lettermint.api("api-token", server.url("/v1").toString()); - String pong = api.ping(); - - RecordedRequest request = server.takeRequest(); - assertEquals("/v1/ping", request.getPath()); - assertEquals("Bearer api-token", request.getHeader("Authorization")); - assertNull(request.getHeader("x-lettermint-token")); - assertEquals("pong", pong); - } - } - - @Test - void apiBlockedFileTypesUsesBearerToken() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse() - .setHeader("Content-Type", "application/json") - .setBody("{\"extensions\":[\"exe\"],\"mime_types\":[\"application/x-msdownload\"]}")); - server.start(); - - ApiClient api = Lettermint.api("api-token", server.url("/v1").toString()); - co.lettermint.models.api.BlockedFileTypesResponse response = api.blockedFileTypes(); - - RecordedRequest request = server.takeRequest(); - assertEquals("/v1/blocked-file-types", request.getPath()); - assertEquals("Bearer api-token", request.getHeader("Authorization")); - assertNull(request.getHeader("x-lettermint-token")); - assertEquals("exe", response.extensions.get(0)); - } - } - - @Test - void sendsBatchEmailsWithTypedPayloads() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse() - .setHeader("Content-Type", "application/json") - .setBody("[{\"message_id\":\"msg_123\",\"status\":\"queued\",\"sandbox\":true,\"sandbox_result\":\"hard_bounced\"}]")); - server.start(); - - SendMailRequest payload = new SendMailRequest(); - payload.fromValue = "from@example.com"; - payload.to = Collections.singletonList("to@example.com"); - payload.subject = "Hello"; - payload.sandboxResult = co.lettermint.models.api.SandboxResult.HARDBOUNCED; - - List response = Lettermint - .email("sending-token", server.url("/v1").toString()) - .idempotencyKey("batch-key") - .sendBatch(Collections.singletonList(payload)); - - RecordedRequest request = server.takeRequest(); - assertEquals("/v1/send/batch", request.getPath()); - assertEquals("sending-token", request.getHeader("x-lettermint-token")); - assertEquals("batch-key", request.getHeader("Idempotency-Key")); - assertTrue(request.getBody().readUtf8().contains("\"sandbox_result\":\"hard_bounced\"")); - assertEquals("msg_123", response.get(0).messageId); - assertTrue(response.get(0).sandbox); - assertEquals("hard_bounced", response.get(0).sandboxResult); - } - } - - @Test - void apiEndpointPathsAreEncodedAndTyped() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"id\":\"domain_123\"}")); - server.enqueue(new MockResponse().setBody("")); - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"data\":{\"verified\":true}}")); - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"data\":[]}")); - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"id\":\"user/id\"}")); - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"id\":\"user/id\"}")); - server.start(); - - ApiClient api = Lettermint.api("api-token", server.url("/v1").toString()); - - assertEquals("domain_123", api.domains().retrieve("domain/id").id); - assertEquals("", api.messages().html("msg/id")); - assertTrue(api.routes().verifyInboundDomain("route/id").data.containsKey("verified")); - assertTrue(api.team().roles().data.isEmpty()); - assertEquals("user/id", api.team().member("user/id").id); - - co.lettermint.models.api.UpdateTeamMemberAssignmentData assignment = - new co.lettermint.models.api.UpdateTeamMemberAssignmentData(); - assignment.roleId = "role_123"; - assignment.projectAccess = Collections.singletonMap("scope", "all"); - assertEquals("user/id", api.team().updateMemberAssignment("user/id", assignment).id); - - assertEquals("/v1/domains/domain%2Fid", server.takeRequest().getPath()); - assertEquals("/v1/messages/msg%2Fid/html", server.takeRequest().getPath()); - assertEquals("/v1/routes/route%2Fid/verify-inbound-domain", server.takeRequest().getPath()); - assertEquals("/v1/team/roles", server.takeRequest().getPath()); - assertEquals("/v1/team/members/user%2Fid", server.takeRequest().getPath()); - RecordedRequest assignmentRequest = server.takeRequest(); - assertEquals("PUT", assignmentRequest.getMethod()); - assertEquals("/v1/team/members/user%2Fid/assignment", assignmentRequest.getPath()); - assertTrue(assignmentRequest.getBody().readUtf8().contains("\"role_id\":\"role_123\"")); - } - } - - @Test - void rawMessageEndpointsPreserveResponseBody() throws Exception { - try (MockWebServer server = new MockWebServer()) { - String rawBody = "Subject: Test\r\n\r\nBody with trailing newline\n"; - server.enqueue(new MockResponse().setBody(rawBody)); - server.start(); - - ApiClient api = Lettermint.api("api-token", server.url("/v1").toString()); - - assertEquals(rawBody, api.messages().source("msg_123")); - } - } - - @Test - void schedulesMessageChangesWithTypedResponses() throws Exception { - try (MockWebServer server = new MockWebServer()) { - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"message_id\":\"msg/id\",\"status\":\"scheduled\",\"scheduled_at\":\"2026-08-27T09:00:00Z\"}")); - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json").setBody("{\"message_id\":\"msg/id\",\"status\":\"canceled\",\"scheduled_at\":null}")); - server.enqueue(new MockResponse().setResponseCode(202).setHeader("Content-Type", "application/json").setBody("{\"data\":{\"message_id\":\"msg/id\",\"status\":\"queued\",\"webhook_target_count\":1}}")); - server.start(); - - ApiClient api = Lettermint.api("api-token", server.url("/v1").toString()); - co.lettermint.models.api.RescheduleMessageRequest payload = new co.lettermint.models.api.RescheduleMessageRequest(); - payload.scheduledAt = "2026-08-27T09:00:00Z"; - assertEquals("scheduled", api.messages().reschedule("msg/id", payload).status); - co.lettermint.models.api.CancelScheduledMessageResponse cancelResponse = api.messages().cancel("msg/id"); - co.lettermint.models.api.RescheduleMessageResponse legacyResponse = cancelResponse; - assertEquals("msg/id", legacyResponse.messageId); - assertEquals("canceled", legacyResponse.status); - assertNull(legacyResponse.scheduledAt); - assertEquals("queued", api.messages().process("msg/id").data.get("status")); - - RecordedRequest reschedule = server.takeRequest(); - assertEquals("PATCH", reschedule.getMethod()); - assertEquals("/v1/messages/msg%2Fid", reschedule.getPath()); - assertTrue(reschedule.getBody().readUtf8().contains("scheduled_at")); - RecordedRequest cancel = server.takeRequest(); - assertEquals("POST", cancel.getMethod()); - assertEquals("/v1/messages/msg%2Fid/cancel", cancel.getPath()); - assertEquals("Bearer api-token", cancel.getHeader("Authorization")); - assertEquals("", cancel.getBody().readUtf8()); - RecordedRequest process = server.takeRequest(); - assertEquals("POST", process.getMethod()); - assertEquals("/v1/messages/msg%2Fid/process", process.getPath()); - } - } - - @Test - void publicClientRejectsAbsoluteRequestPaths() throws Exception { - Lettermint lettermint = new Lettermint("sending-token", "https://api.example.test/v1"); - - IllegalArgumentException exception = assertThrows( - IllegalArgumentException.class, - () -> lettermint.getClient().post("https://attacker.example.test/collect", Collections.emptyMap(), Map.class) - ); - - assertEquals("Request path must be relative", exception.getMessage()); - } - - @Test - void generatedApiModelsMatchCurrentTeamSchema() { - assertEquals("scheduled", co.lettermint.models.api.MessageEventType.SCHEDULED); - assertEquals("message.auto_replied", co.lettermint.models.api.WebhookEvent.MESSAGEAUTOREPLIED); - assertEquals("admin", co.lettermint.models.api.BuiltInTeamRole.ADMIN); - assertEquals("enforced", co.lettermint.models.api.TlsPolicy.ENFORCED); - - co.lettermint.models.api.UpdateRouteSettingsData settings = new co.lettermint.models.api.UpdateRouteSettingsData(); - settings.redactEmailContent = true; - settings.generatePlaintextFallback = false; - settings.tls = co.lettermint.models.api.TlsPolicy.ENFORCED; - - co.lettermint.models.api.UpdateRouteInboundSettingsData inboundSettings = new co.lettermint.models.api.UpdateRouteInboundSettingsData(); - inboundSettings.inboundSpamThreshold = 3.0; - - co.lettermint.models.api.UpdateRouteData routeUpdate = new co.lettermint.models.api.UpdateRouteData(); - routeUpdate.settings = settings; - routeUpdate.inboundSettings = inboundSettings; - - co.lettermint.models.api.UpdateProjectData projectUpdate = new co.lettermint.models.api.UpdateProjectData(); - projectUpdate.redactEmailContent = false; - - co.lettermint.models.api.ProjectData project = new co.lettermint.models.api.ProjectData(); - project.redactEmailContent = true; - - co.lettermint.models.api.StoreProjectData projectCreate = new co.lettermint.models.api.StoreProjectData(); - projectCreate.shortToken = true; - - co.lettermint.models.api.BlockedFileTypesResponse blockedFileTypes = new co.lettermint.models.api.BlockedFileTypesResponse(); - blockedFileTypes.extensions = Collections.singletonList("exe"); - blockedFileTypes.mimeTypes = Collections.singletonList("application/x-msdownload"); - - co.lettermint.models.api.TeamData team = new co.lettermint.models.api.TeamData(); - team.includedVolume = 300000; - - co.lettermint.models.api.TeamRoleData role = new co.lettermint.models.api.TeamRoleData(); - role.assignable = true; - role.permissions = Collections.singletonList(co.lettermint.models.api.RbacPermission.MEMBERSMANAGE); - - co.lettermint.models.api.UpdateTeamMemberAssignmentData assignment = - new co.lettermint.models.api.UpdateTeamMemberAssignmentData(); - assignment.roleId = "role_123"; - assignment.projectAccess = Collections.singletonMap("scope", "selected"); - - co.lettermint.models.api.DomainData domain = new co.lettermint.models.api.DomainData(); - domain.dkimMode = co.lettermint.models.api.DkimMode.MANAGEDCNAME; - - co.lettermint.models.api.SuppressedRecipientData suppressedRecipient = new co.lettermint.models.api.SuppressedRecipientData(); - suppressedRecipient.sourceMessage = new co.lettermint.models.api.SuppressionSourceMessageData(); - suppressedRecipient.sourceMessage.id = "msg_123"; - - co.lettermint.models.api.MessageListData message = new co.lettermint.models.api.MessageListData(); - message.spamScore = 2.5; - message.scheduledAt = "2026-08-27T09:00:00Z"; - - co.lettermint.models.api.SendMailRequest sandboxSend = new co.lettermint.models.api.SendMailRequest(); - sandboxSend.sandboxResult = co.lettermint.models.api.SandboxResult.CLICKED; - co.lettermint.models.api.MessageRecipientData recipient = new co.lettermint.models.api.MessageRecipientData(); - recipient.sandboxResult = co.lettermint.models.api.SandboxResult.CLICKED; - project.deliveryMode = co.lettermint.models.api.DeliveryMode.SANDBOX; - co.lettermint.models.api.WebhookDeliveryData delivery = new co.lettermint.models.api.WebhookDeliveryData(); - delivery.sandbox = true; - co.lettermint.models.api.StoreWebhookData webhook = new co.lettermint.models.api.StoreWebhookData(); - webhook.deliveryModeFilter = co.lettermint.models.api.WebhookDeliveryModeFilter.BOTH; - co.lettermint.models.api.CursorPaginator cursor = new co.lettermint.models.api.CursorPaginator(); - cursor.perPage = 25; - cursor.data = Collections.emptyList(); - - assertFalse(routeUpdate.settings.generatePlaintextFallback); - assertEquals("enforced", routeUpdate.settings.tls); - assertEquals(3.0, routeUpdate.inboundSettings.inboundSpamThreshold); - assertFalse(projectUpdate.redactEmailContent); - assertTrue(projectCreate.shortToken); - assertTrue(project.redactEmailContent); - assertEquals("team", co.lettermint.models.api.SuppressionScope.TEAM); - assertEquals("application/x-msdownload", blockedFileTypes.mimeTypes.get(0)); - assertEquals(300000, team.includedVolume); - assertTrue(role.assignable); - assertEquals("members:manage", role.permissions.get(0)); - assertEquals("role_123", assignment.roleId); - assertEquals("managed_cname", domain.dkimMode); - assertEquals("msg_123", suppressedRecipient.sourceMessage.id); - assertEquals(2.5, message.spamScore); - assertEquals("2026-08-27T09:00:00Z", message.scheduledAt); - assertEquals("clicked", sandboxSend.sandboxResult); - assertEquals("clicked", recipient.sandboxResult); - assertEquals("sandbox", project.deliveryMode); - assertTrue(delivery.sandbox); - assertEquals("both", webhook.deliveryModeFilter); - assertEquals(25, cursor.perPage); - assertTrue(cursor.data.isEmpty()); - } - - @Test - void apiExposesDocumentedOperations() throws Exception { - ApiClient api = Lettermint.api("api-token"); - Map methods = new HashMap<>(); - methods.put("domain.index", api.domains().getClass().getMethod("list")); - methods.put("domain.store", api.domains().getClass().getMethod("create", co.lettermint.models.api.StoreDomainData.class)); - methods.put("domain.show", api.domains().getClass().getMethod("retrieve", String.class)); - methods.put("domain.destroy", api.domains().getClass().getMethod("delete", String.class)); - methods.put("domain.verifyDnsRecords", api.domains().getClass().getMethod("verifyDnsRecords", String.class)); - methods.put("domain.verifySpecificDnsRecord", api.domains().getClass().getMethod("verifyDnsRecord", String.class, String.class)); - methods.put("domain.updateProjects", api.domains().getClass().getMethod("updateProjects", String.class, co.lettermint.models.api.UpdateDomainProjectsData.class)); - methods.put("v1.ping", api.getClass().getMethod("ping")); - methods.put("v1.analytics", api.getClass().getMethod("analytics", co.lettermint.models.api.AnalyticsRequest.class)); - methods.put("getReportForwarding", api.projects().getClass().getMethod("retrieveReportForwarding", String.class)); - methods.put("updateReportForwarding", api.projects().getClass().getMethod("updateReportForwarding", String.class, co.lettermint.models.api.ReportForwardingRequest.class)); - methods.put("deleteReportForwarding", api.projects().getClass().getMethod("deleteReportForwarding", String.class)); - methods.put("verifyReportForwarding", api.projects().getClass().getMethod("verifyReportForwarding", String.class, co.lettermint.models.api.VerifyReportForwardingRequest.class)); - methods.put("resendReportForwardingCode", api.projects().getClass().getMethod("resendReportForwardingCode", String.class)); - methods.put("v1.blockedFileTypes", api.getClass().getMethod("blockedFileTypes")); - methods.put("message.index", api.messages().getClass().getMethod("list")); - methods.put("message.show", api.messages().getClass().getMethod("retrieve", String.class)); - methods.put("rescheduleMessage", api.messages().getClass().getMethod("reschedule", String.class, co.lettermint.models.api.RescheduleMessageRequest.class)); - methods.put("cancelScheduledMessage", api.messages().getClass().getMethod("cancel", String.class)); - methods.put("processInboundMessage", api.messages().getClass().getMethod("process", String.class)); - methods.put("message.events", api.messages().getClass().getMethod("events", String.class)); - methods.put("message.source", api.messages().getClass().getMethod("source", String.class)); - methods.put("message.html", api.messages().getClass().getMethod("html", String.class)); - methods.put("message.text", api.messages().getClass().getMethod("text", String.class)); - methods.put("project.index", api.projects().getClass().getMethod("list")); - methods.put("project.store", api.projects().getClass().getMethod("create", co.lettermint.models.api.StoreProjectData.class)); - methods.put("project.show", api.projects().getClass().getMethod("retrieve", String.class)); - methods.put("project.update", api.projects().getClass().getMethod("update", String.class, co.lettermint.models.api.UpdateProjectData.class)); - methods.put("project.destroy", api.projects().getClass().getMethod("delete", String.class)); - methods.put("project.rotateToken", api.projects().getClass().getMethod("rotateToken", String.class)); - methods.put("route.index", api.projects().getClass().getMethod("routes", String.class)); - methods.put("route.store", api.projects().getClass().getMethod("createRoute", String.class, co.lettermint.models.api.StoreRouteData.class)); - methods.put("route.show", api.routes().getClass().getMethod("retrieve", String.class)); - methods.put("route.update", api.routes().getClass().getMethod("update", String.class, co.lettermint.models.api.UpdateRouteData.class)); - methods.put("route.destroy", api.routes().getClass().getMethod("delete", String.class)); - methods.put("route.verifyInboundDomain", api.routes().getClass().getMethod("verifyInboundDomain", String.class)); - methods.put("stats.index", api.stats().getClass().getMethod("retrieve")); - methods.put("suppression.index", api.suppressions().getClass().getMethod("list")); - methods.put("suppression.store", api.suppressions().getClass().getMethod("create", co.lettermint.models.api.StoreSuppressionData.class)); - methods.put("suppression.destroy", api.suppressions().getClass().getMethod("delete", String.class)); - methods.put("team.show", api.team().getClass().getMethod("retrieve")); - methods.put("team.update", api.team().getClass().getMethod("update", co.lettermint.models.api.UpdateTeamData.class)); - methods.put("team.usage", api.team().getClass().getMethod("usage")); - methods.put("team.roles", api.team().getClass().getMethod("roles")); - methods.put("team.members", api.team().getClass().getMethod("members")); - methods.put("team.members.show", api.team().getClass().getMethod("member", String.class)); - methods.put("team.members.assignment.update", api.team().getClass().getMethod("updateMemberAssignment", String.class, co.lettermint.models.api.UpdateTeamMemberAssignmentData.class)); - methods.put("webhook.index", api.webhooks().getClass().getMethod("list")); - methods.put("webhook.store", api.webhooks().getClass().getMethod("create", co.lettermint.models.api.StoreWebhookData.class)); - methods.put("webhook.show", api.webhooks().getClass().getMethod("retrieve", String.class)); - methods.put("webhook.update", api.webhooks().getClass().getMethod("update", String.class, co.lettermint.models.api.UpdateWebhookData.class)); - methods.put("webhook.destroy", api.webhooks().getClass().getMethod("delete", String.class)); - methods.put("webhook.test", api.webhooks().getClass().getMethod("test", String.class)); - methods.put("webhook.regenerateSecret", api.webhooks().getClass().getMethod("regenerateSecret", String.class)); - methods.put("webhook.deliveries", api.webhooks().getClass().getMethod("deliveries", String.class)); - methods.put("webhook.showDelivery", api.webhooks().getClass().getMethod("delivery", String.class, String.class)); - - for (Map.Entry entry : methods.entrySet()) { - assertNotNull(entry.getValue(), "Missing SDK method for " + entry.getKey()); - } - } -} diff --git a/src/test/java/co/lettermint/CancelBinaryCompatibilityTest.java b/src/test/java/co/lettermint/CancelBinaryCompatibilityTest.java deleted file mode 100644 index f5a0510..0000000 --- a/src/test/java/co/lettermint/CancelBinaryCompatibilityTest.java +++ /dev/null @@ -1,87 +0,0 @@ -package co.lettermint; - -import co.lettermint.api.ApiClient; -import co.lettermint.models.api.CancelScheduledMessageResponse; -import co.lettermint.models.api.RescheduleMessageResponse; -import co.lettermint.models.api.RouteData; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.io.TempDir; - -import javax.tools.JavaCompiler; -import javax.tools.ToolProvider; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.*; - -class CancelBinaryCompatibilityTest { - @TempDir - Path temporary; - - @Test - void callerCompiledAgainstOriginalPr53DescriptorStillRuns() throws Exception { - // PR #53 base: 8e3f4b1b0cbad79fbda6e6d0c724d18a899a2b0b. - Path stub = temporary.resolve("co/lettermint/api/ApiClient.java"); - Files.createDirectories(stub.getParent()); - Files.write(stub, ("package co.lettermint.api; " - + "import co.lettermint.models.api.RescheduleMessageResponse; " - + "public class ApiClient { public static class MessagesEndpoint { " - + "public RescheduleMessageResponse cancel(String id) { return null; } } }") - .getBytes(StandardCharsets.UTF_8)); - Path caller = temporary.resolve("OldCaller.java"); - Files.write(caller, ("import co.lettermint.api.ApiClient; " - + "import co.lettermint.models.api.RescheduleMessageResponse; " - + "public class OldCaller { " - + "public static RescheduleMessageResponse cancel(ApiClient.MessagesEndpoint endpoint) { " - + "return endpoint.cancel(\"message_1\"); } }").getBytes(StandardCharsets.UTF_8)); - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - assertNotNull(compiler, "This test requires a JDK, not a JRE"); - assertEquals(0, compiler.run(null, null, null, "-classpath", - System.getProperty("java.class.path"), "-d", temporary.toString(), - stub.toString(), caller.toString())); - - try (MockWebServer server = new MockWebServer(); - URLClassLoader oldCaller = new URLClassLoader(new URL[]{temporary.toUri().toURL()}, - ApiClient.class.getClassLoader())) { - server.enqueue(new MockResponse().setHeader("Content-Type", "application/json") - .setBody("{\"message_id\":\"message_1\",\"status\":\"canceled\"}")); - server.start(); - ApiClient api = Lettermint.api("token", server.url("/v1").toString()); - Object value = oldCaller.loadClass("OldCaller") - .getMethod("cancel", ApiClient.MessagesEndpoint.class).invoke(null, api.messages()); - assertTrue(value instanceof CancelScheduledMessageResponse); - assertTrue(value instanceof RescheduleMessageResponse); - assertEquals("message_1", ((RescheduleMessageResponse) value).messageId); - assertEquals("canceled", ((RescheduleMessageResponse) value).status); - okhttp3.mockwebserver.RecordedRequest request = server.takeRequest(); - assertEquals("POST", request.getMethod()); - assertEquals("/v1/messages/message_1/cancel", request.getPath()); - } - } - - @Test - void currentReturnTypeAndOldSourceAssignmentBothCompile() { - assertTrue(RescheduleMessageResponse.class.isAssignableFrom(CancelScheduledMessageResponse.class)); - } - - private static RescheduleMessageResponse oldSourceCaller(ApiClient api) { - return api.messages().cancel("message_1"); - } - - @Test - void inboundRouteDomainIsOptionalAndNullable() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - RouteData populated = mapper.readValue("{\"inbound_route_domain\":\"incoming.example.com\"}", RouteData.class); - assertEquals("incoming.example.com", populated.inboundRouteDomain); - assertEquals("incoming.example.com", - mapper.readValue(mapper.writeValueAsString(populated), RouteData.class).inboundRouteDomain); - assertNull(mapper.readValue("{\"inbound_route_domain\":null}", RouteData.class).inboundRouteDomain); - assertNull(mapper.readValue("{}", RouteData.class).inboundRouteDomain); - } -} diff --git a/src/test/java/co/lettermint/ClientTest.java b/src/test/java/co/lettermint/ClientTest.java new file mode 100644 index 0000000..04d777d --- /dev/null +++ b/src/test/java/co/lettermint/ClientTest.java @@ -0,0 +1,174 @@ +package co.lettermint; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import co.lettermint.exceptions.LettermintConfigException; +import co.lettermint.exceptions.ServerException; +import co.lettermint.types.RescheduleMessageRequest; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import java.net.http.HttpClient; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class ClientTest { + static final String SENDING = "lm_SendingTestToken0123456789abcdefAB"; + static final String TEAM = "lm_team_TeamTestToken0123456789abcdefABCDEFGH"; + + private FakeServer server; + + @BeforeEach + void start() throws Exception { + server = new FakeServer(); + server.fallback(request -> request.path().equals("/v1/ping") + ? FakeServer.Response.text(200, "text/html; charset=UTF-8", "pong\n") + : FakeServer.Response.json(200, "{}")); + } + + @AfterEach + void stop() { + server.close(); + } + + private Lettermint.Builder builder() { + return Lettermint.builder().baseUrl(server.baseUrl()); + } + + @Test + void requiresAToken() { + LettermintConfigException error = assertThrows(LettermintConfigException.class, () -> Lettermint.builder().build()); + assertEquals("Pass sendingToken, teamToken or both.", error.getMessage()); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().sendingToken("")); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().teamToken("lm_team_with space")); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().sendingToken("lm_abc\r\nx")); + } + + @Test + void detectsTheTokenFormat() { + Lettermint team = builder().token(TEAM).build(); + assertEquals("pong", team.ping()); + assertEquals("Bearer " + TEAM, server.last().header("authorization")); + assertNull(server.last().header("x-lettermint-token")); + + for (String sending : List.of("lm_Proj32Conformance0Token1Fake2Val", "lm_Proj22Conformance0Toke")) { + Lettermint client = builder().token(sending).build(); + assertEquals("pong", client.ping()); + assertEquals(sending, server.last().header("x-lettermint-token")); + assertNull(server.last().header("authorization")); + } + int before = server.requests().size(); + for (String invalid : new String[] {"lm_sso_SsoToken123", "", "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4In0.c2ln", "sk_live_123", "lm_team_", "lm_", null}) { + LettermintConfigException error = assertThrows(LettermintConfigException.class, () -> Lettermint.of(invalid)); + assertTrue(error.getMessage().startsWith("Unrecognised token format"), error.getMessage()); + if (invalid != null && invalid.length() > 3) { + assertFalse(error.getMessage().contains(invalid)); + } + } + assertEquals(before, server.requests().size()); + } + + @Test + void eachPartUsesItsOwnTokenAndNeverFallsBack() { + Lettermint sending = builder().sendingToken(SENDING).build(); + LettermintConfigException error = assertThrows(LettermintConfigException.class, () -> sending.domains().list()); + assertEquals("domains.list needs teamToken; set it with Lettermint.builder().teamToken(...).", error.getMessage()); + assertThrows(LettermintConfigException.class, () -> sending.webhooks().deliveries().iterate("wh_1")); + assertThrows(LettermintConfigException.class, () -> sending.analytics(null)); + + Lettermint team = builder().teamToken(TEAM).build(); + error = assertThrows(LettermintConfigException.class, () -> team.emails().send(EmailMessage.create())); + assertEquals("emails.send needs sendingToken; set it with Lettermint.builder().sendingToken(...).", error.getMessage()); + assertThrows(LettermintConfigException.class, () -> team.emails().compose()); + assertThrows(LettermintConfigException.class, () -> team.emails().ping()); + assertTrue(server.requests().isEmpty()); + } + + @Test + void pingRescheduleAndCancelPreferTheTeamToken() { + Lettermint both = builder().sendingToken(SENDING).teamToken(TEAM).build(); + both.ping(); + assertEquals("Bearer " + TEAM, server.last().header("authorization")); + both.emails().ping(); + assertEquals(SENDING, server.last().header("x-lettermint-token")); + assertNull(server.last().header("authorization")); + both.messages().cancel("msg_1"); + assertEquals("Bearer " + TEAM, server.last().header("authorization")); + + Lettermint sending = builder().sendingToken(SENDING).build(); + sending.ping(); + assertEquals(SENDING, server.last().header("x-lettermint-token")); + sending.messages().reschedule("msg_1", RescheduleMessageRequest.builder().scheduledAt("2026-10-20T09:00:00Z").build()); + assertEquals("PATCH", server.last().method()); + assertEquals(SENDING, server.last().header("x-lettermint-token")); + sending.messages().cancel("msg_1"); + assertEquals(SENDING, server.last().header("x-lettermint-token")); + assertNull(server.last().header("authorization")); + } + + @Test + void validatesOptions() { + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().baseUrl("ftp://example.com")); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().baseUrl("/v1")); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().baseUrl("https://user:pass@example.com/v1")); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().baseUrl("https://example.com/v1?x=1")); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().timeout(Duration.ZERO)); + assertThrows(LettermintConfigException.class, () -> Lettermint.builder().timeout(Duration.ofSeconds(-1))); + HttpClient following = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build(); + LettermintConfigException error = assertThrows(LettermintConfigException.class, () -> Lettermint.builder().httpClient(following)); + assertTrue(error.getMessage().contains("must not follow redirects")); + assertDoesNotThrow(() -> Lettermint.builder().httpClient(HttpClient.newHttpClient())); + + Lettermint client = Lettermint.builder().sendingToken(SENDING).baseUrl("https://example.com/v1///").build(); + assertTrue(client.toString().contains("baseUrl=https://example.com/v1,"), client.toString()); + } + + @Test + void usesAnInjectedHttpClient() { + Lettermint client = builder().teamToken(TEAM).httpClient(HttpClient.newBuilder().build()).build(); + assertEquals("pong", client.ping()); + } + + @Test + void sendsTheUserAgent() { + builder().teamToken(TEAM).build().ping(); + assertTrue(server.last().header("user-agent").startsWith("lettermint-java/"), server.last().header("user-agent")); + assertEquals("application/json", server.last().header("accept")); + } + + @Test + void neverPrintsTokens() throws Exception { + Lettermint client = builder().sendingToken(SENDING).teamToken(TEAM).timeout(Duration.ofSeconds(5)).build(); + Lettermint.Builder builder = Lettermint.builder().sendingToken(SENDING).teamToken(TEAM); + server.enqueue(FakeServer.Response.json(500, "{\"message\":\"Server Error\"}")); + ServerException failure = assertThrows(ServerException.class, () -> client.emails().compose().from("a@b.c").to("d@e.f").subject("s").send()); + + List subjects = new ArrayList<>(List.of(client, builder, client.emails(), client.domains(), client.messages(), client.projects(), + client.projects().reportForwarding(), client.routes(), client.stats(), client.suppressions(), client.team(), client.team().members(), + client.webhooks(), client.webhooks().deliveries(), client.emails().compose().from("a@b.c"), client.domains().iterate(), failure)); + ObjectMapper lenient = new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); + for (Object subject : subjects) { + List renders = new ArrayList<>(List.of(subject.toString(), String.valueOf(subject), String.format("%s", subject))); + try { + renders.add(lenient.writeValueAsString(subject)); + } catch (Exception ignored) { + // A failed serialization does not leak anything. + } + for (String render : renders) { + assertFalse(render.contains(SENDING), subject.getClass() + ": " + render); + assertFalse(render.contains(TEAM), subject.getClass() + ": " + render); + } + } + assertEquals("Lettermint{baseUrl=" + server.baseUrl() + ", timeout=PT5S, sendingToken=[redacted], teamToken=[redacted]}", client.toString()); + assertEquals("Domains{}", client.domains().toString()); + assertFalse(failure.getMessage().contains(SENDING)); + } +} diff --git a/src/test/java/co/lettermint/EmailEndpointTest.java b/src/test/java/co/lettermint/EmailEndpointTest.java deleted file mode 100644 index 6c66383..0000000 --- a/src/test/java/co/lettermint/EmailEndpointTest.java +++ /dev/null @@ -1,303 +0,0 @@ -package co.lettermint; - -import co.lettermint.models.SendEmailResponse; -import co.lettermint.models.MessageTag; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; - -class EmailEndpointTest { - - private MockWebServer mockWebServer; - private Lettermint lettermint; - - @BeforeEach - void setUp() throws IOException { - mockWebServer = new MockWebServer(); - mockWebServer.start(); - String baseUrl = mockWebServer.url("/v1").toString(); - lettermint = new Lettermint("test-api-token", baseUrl); - } - - @AfterEach - void tearDown() throws IOException { - mockWebServer.shutdown(); - } - - @Test - void testSimpleEmail() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_123\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - SendEmailResponse response = lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test Subject") - .text("Hello World") - .send(); - - assertEquals("msg_123", response.getMessageId()); - assertEquals("queued", response.getStatus()); - - RecordedRequest request = mockWebServer.takeRequest(); - assertEquals("POST", request.getMethod()); - assertEquals("/v1/send", request.getPath()); - assertTrue(request.getHeader("Content-Type").startsWith("application/json")); - assertEquals("test-api-token", request.getHeader("x-lettermint-token")); - assertTrue(request.getHeader("User-Agent").startsWith("Lettermint/")); - } - - @Test - void testEmailWithAllOptions() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\":\"msg_456\",\"status\":\"queued\",\"sandbox\":true,\"sandbox_result\":\"deferred\"}") - .setHeader("Content-Type", "application/json")); - - Map headers = new HashMap<>(); - headers.put("Message-ID", ""); - headers.put("X-LM-Preserve-Message-ID", "true"); - - Map metadata = new HashMap<>(); - metadata.put("userId", "user_123"); - metadata.put("campaign", "welcome"); - - Map tags = new HashMap<>(); - tags.put("name", "campaign"); - tags.put("value", "welcome-v2"); - - Map settings = new HashMap<>(); - settings.put("track_opens", false); - settings.put("track_clicks", true); - settings.put("tls", "enforced"); - - SendEmailResponse response = lettermint.email() - .from("John Doe ") - .to("recipient1@example.com", "recipient2@example.com") - .cc("cc@example.com") - .bcc("bcc@example.com") - .replyTo("reply@example.com") - .subject("Welcome!") - .html("

Hello World

") - .text("Hello World") - .headers(headers) - .attach("document.pdf", "base64content") - .attach("logo.png", "base64logo", "logo-cid") - .attach("invite.ics", "base64icalFile", null, "text/calendar; method=REQUEST") - .route("route-slug-123") - .metadata(metadata) - .tag("welcome") - .tags(tags) - .settings(settings) - .sandboxResult(co.lettermint.models.api.SandboxResult.DEFERRED) - .idempotencyKey("unique-key-123") - .send(); - - assertEquals("msg_456", response.getMessageId()); - assertTrue(response.getSandbox()); - assertEquals("deferred", response.getSandboxResult()); - - RecordedRequest request = mockWebServer.takeRequest(); - assertEquals("unique-key-123", request.getHeader("Idempotency-Key")); - - String body = request.getBody().readUtf8(); - assertTrue(body.contains("\"from\":\"John Doe \"")); - assertTrue(body.contains("\"to\":[\"recipient1@example.com\",\"recipient2@example.com\"]")); - assertTrue(body.contains("\"cc\":[\"cc@example.com\"]")); - assertTrue(body.contains("\"bcc\":[\"bcc@example.com\"]")); - assertTrue(body.contains("\"reply_to\":[\"reply@example.com\"]")); - assertTrue(body.contains("\"subject\":\"Welcome!\"")); - assertTrue(body.contains("\"html\":\"

Hello World

\"")); - assertTrue(body.contains("\"text\":\"Hello World\"")); - assertTrue(body.contains("\"route\":\"route-slug-123\"")); - assertTrue(body.contains("\"tag\":\"welcome\"")); - assertTrue(body.contains("\"tags\"")); - assertTrue(body.contains("\"settings\":")); - assertTrue(body.contains("\"track_opens\":false")); - assertTrue(body.contains("\"track_clicks\":true")); - assertTrue(body.contains("\"tls\":\"enforced\"")); - assertTrue(body.contains("\"Message-ID\":\"\"")); - assertTrue(body.contains("\"X-LM-Preserve-Message-ID\":\"true\"")); - assertTrue(body.contains("\"sandbox_result\":\"deferred\"")); - assertTrue(body.contains("{\"filename\":\"document.pdf\",\"content\":\"base64content\"}")); - assertTrue(body.contains("{\"filename\":\"logo.png\",\"content\":\"base64logo\",\"content_id\":\"logo-cid\"}")); - assertTrue(body.contains("{\"filename\":\"invite.ics\",\"content\":\"base64icalFile\",\"content_type\":\"text/calendar; method=REQUEST\"}")); - } - - @Test - void testRecipientsReplaceWhenCalledMultipleTimes() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_789\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("first@example.com") - .to("replaced@example.com") - .subject("Test") - .text("Test") - .send(); - - RecordedRequest request = mockWebServer.takeRequest(); - String body = request.getBody().readUtf8(); - - assertTrue(body.contains("\"to\":[\"replaced@example.com\"]")); - assertFalse(body.contains("first@example.com")); - } - - @Test - void testEndpointResetsAfterSend() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_1\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_2\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("First Email") - .text("First content") - .send(); - - lettermint.email() - .from("sender@example.com") - .to("other@example.com") - .subject("Second Email") - .text("Second content") - .send(); - - mockWebServer.takeRequest(); - RecordedRequest secondRequest = mockWebServer.takeRequest(); - String body = secondRequest.getBody().readUtf8(); - - assertTrue(body.contains("\"subject\":\"Second Email\"")); - assertFalse(body.contains("First Email")); - } - - @Test - void testSingleHeaderMethod() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_123\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test") - .text("Test") - .header("X-First", "value1") - .header("X-Second", "value2") - .send(); - - RecordedRequest request = mockWebServer.takeRequest(); - String body = request.getBody().readUtf8(); - - assertTrue(body.contains("\"X-First\":\"value1\"")); - assertTrue(body.contains("\"X-Second\":\"value2\"")); - } - - @Test - void testReplyToSingleString() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_123\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test") - .text("Test") - .replyTo("reply@example.com") - .send(); - - RecordedRequest request = mockWebServer.takeRequest(); - String body = request.getBody().readUtf8(); - - assertTrue(body.contains("\"reply_to\":[\"reply@example.com\"]")); - } - - @Test - void testReplyToMultipleAddresses() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_123\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test") - .text("Test") - .replyTo("reply1@example.com", "reply2@example.com") - .send(); - - RecordedRequest request = mockWebServer.takeRequest(); - String body = request.getBody().readUtf8(); - - assertTrue(body.contains("\"reply_to\":[\"reply1@example.com\",\"reply2@example.com\"]")); - } - - @Test - void testSingleMetadataMethod() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_123\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test") - .text("Test") - .metadata("key1", "value1") - .metadata("key2", 123) - .send(); - - RecordedRequest request = mockWebServer.takeRequest(); - String body = request.getBody().readUtf8(); - - assertTrue(body.contains("\"key1\":\"value1\"")); - assertTrue(body.contains("\"key2\":123")); - } - - @Test - void testTypedMessageTags() throws Exception { - mockWebServer.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_123\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test") - .text("Test") - .tags(new MessageTag("campaign", "welcome"), new MessageTag("customer", "new")) - .send(); - - String body = mockWebServer.takeRequest().getBody().readUtf8(); - assertTrue(body.contains("\"tags\":[{\"name\":\"campaign\",\"value\":\"welcome\"}")); - } - - @Test - void testMessageTagValidation() { - assertThrows(IllegalArgumentException.class, () -> new MessageTag("invalid name", "value")); - assertThrows(IllegalArgumentException.class, () -> new MessageTag("__LETTERMINT_internal", "value")); - assertThrows(IllegalArgumentException.class, () -> lettermint.email().tags( - new MessageTag("same", "one"), new MessageTag("same", "two"))); - - MessageTag[] tags = new MessageTag[20]; - for (int index = 0; index < tags.length; index++) { - tags[index] = new MessageTag("tag_" + index, "value"); - } - assertThrows(IllegalArgumentException.class, () -> lettermint.email().tag("legacy").tags(tags)); - } -} diff --git a/src/test/java/co/lettermint/EmailsTest.java b/src/test/java/co/lettermint/EmailsTest.java new file mode 100644 index 0000000..1801c92 --- /dev/null +++ b/src/test/java/co/lettermint/EmailsTest.java @@ -0,0 +1,255 @@ +package co.lettermint; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import co.lettermint.exceptions.LettermintValidationException; +import co.lettermint.types.MessageTagInput; +import co.lettermint.types.SandboxResult; +import co.lettermint.types.SendMailRequestSettings; +import co.lettermint.types.SendMailResponse; +import co.lettermint.types.TlsPolicy; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class EmailsTest { + private static final ObjectMapper JSON = new ObjectMapper(); + + private FakeServer server; + private Lettermint client; + + @BeforeEach + void start() throws Exception { + server = new FakeServer(); + server.fallback(request -> request.path().equals("/v1/send/batch") + ? FakeServer.Response.json(202, "[{\"message_id\":\"m1\",\"status\":\"pending\"},{\"message_id\":\"m2\",\"status\":\"scheduled\",\"scheduled_at\":\"2026-10-20T09:00:00Z\"}]") + : FakeServer.Response.json(202, "{\"message_id\":\"m1\",\"status\":\"pending\",\"sandbox\":true,\"sandbox_result\":\"hard_bounced\"}")); + client = Lettermint.builder().sendingToken(ClientTest.SENDING).baseUrl(server.baseUrl()).build(); + } + + @AfterEach + void stop() { + server.close(); + } + + private JsonNode lastBody() throws Exception { + return JSON.readTree(server.last().body()); + } + + @Test + void sendsEveryFieldInWireFormat() throws Exception { + byte[] pdf = "%PDF-1.4".getBytes(StandardCharsets.UTF_8); + SendMailResponse response = client.emails().compose() + .from("Acme ") + .to("jane@example.com", "john@example.com") + .cc("cc@example.com") + .bcc(List.of("bcc@example.com")) + .replyTo("support@acme.com") + .subject("Welcome") + .html("

Hi

") + .text("Hi") + .headers(Map.of("X-Campaign", "welcome")) + .metadata(Map.of("order_id", "1234")) + .tag("legacy") + .tags(new MessageTagInput("campaign", "welcome")) + .route("transactional") + .scheduledAt(Instant.parse("2026-10-20T09:00:00Z")) + .settings(SendMailRequestSettings.builder().trackOpens(false).tls(TlsPolicy.of("required")).build()) + .sandboxResult(SandboxResult.of("hard_bounced")) + .attach(EmailAttachment.of("invoice.pdf", pdf).contentType("application/pdf")) + .attach(EmailAttachment.ofBase64("logo.png", "aGVsbG8=").contentId("logo")) + .send(SendOptions.idempotencyKey("welcome-jane")); + assertEquals("m1", response.messageId()); + assertTrue(response.sandbox()); + assertEquals("hard_bounced", response.sandboxResult().value()); + + FakeServer.Request request = server.last(); + assertEquals("/v1/send", request.path()); + assertEquals("welcome-jane", request.header("idempotency-key")); + assertEquals(ClientTest.SENDING, request.header("x-lettermint-token")); + JsonNode body = lastBody(); + assertEquals("Acme ", body.get("from").asText()); + assertEquals(List.of("jane@example.com", "john@example.com"), JSON.convertValue(body.get("to"), List.class)); + assertEquals("support@acme.com", body.get("reply_to").get(0).asText()); + assertEquals("2026-10-20T09:00:00Z", body.get("scheduled_at").asText()); + assertEquals("hard_bounced", body.get("sandbox_result").asText()); + assertEquals("{\"track_opens\":false,\"tls\":\"required\"}", body.get("settings").toString()); + assertEquals("[{\"name\":\"campaign\",\"value\":\"welcome\"}]", body.get("tags").toString()); + assertEquals("legacy", body.get("tag").asText()); + assertEquals("{\"filename\":\"invoice.pdf\",\"content\":\"" + Base64.getEncoder().encodeToString(pdf) + "\",\"content_type\":\"application/pdf\"}", + body.get("attachments").get(0).toString()); + assertEquals("{\"filename\":\"logo.png\",\"content\":\"aGVsbG8=\",\"content_id\":\"logo\"}", body.get("attachments").get(1).toString()); + assertEquals(17, body.size()); + } + + @Test + void sendsPlainMessages() throws Exception { + EmailMessage message = EmailMessage.create().from("a@b.c").to("d@e.f").subject("s").html("

x

"); + client.emails().send(message); + assertEquals("{\"from\":\"a@b.c\",\"to\":[\"d@e.f\"],\"subject\":\"s\",\"html\":\"

x

\"}", server.last().body()); + client.emails().send(message.html(null).text("x")); + assertEquals("{\"from\":\"a@b.c\",\"to\":[\"d@e.f\"],\"subject\":\"s\",\"text\":\"x\"}", server.last().body()); + } + + @Test + void buildersAreImmutable() { + EmailBuilder base = client.emails().compose().from("hello@acme.com").subject("Welcome"); + EmailBuilder jane = base.to("jane@example.com").html("

Jane

"); + EmailBuilder john = base.to("john@example.com"); + assertNotSame(base, jane); + assertEquals(List.of(), base.build().to()); + assertNull(base.build().html()); + assertEquals(List.of("jane@example.com"), jane.build().to()); + assertEquals(List.of("john@example.com"), john.build().to()); + assertNull(john.build().html()); + + jane.send(); + jane.send(); + assertEquals(2, server.requests().size()); + assertEquals(server.requests().get(0).body(), server.requests().get(1).body()); + + EmailMessage message = EmailMessage.create().to(new ArrayList<>(List.of("a@b.c"))); + assertThrows(UnsupportedOperationException.class, () -> message.to().add("x@y.z")); + assertSame(EmailMessage.create(), EmailMessage.create()); + assertEquals(message.to(), client.emails().compose(message).build().to()); + } + + @Test + void aThrowingSetterLeavesTheBuilderUnchanged() { + EmailBuilder base = client.emails().compose().from("a@b.c").tags(new MessageTagInput("ok", "1")); + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput("not a valid tag name!", "x"))); + assertEquals(List.of(new MessageTagInput("ok", "1")), base.build().tags()); + base.to("d@e.f").subject("s").send(); + assertEquals("[{\"name\":\"ok\",\"value\":\"1\"}]", server.last().body().replaceAll(".*\"tags\":(\\[[^]]*]).*", "$1")); + } + + @Test + void concurrentSendsFromOneTemplateDoNotMix() throws Exception { + EmailBuilder template = client.emails().compose().from("hello@acme.com").subject("Welcome"); + int count = 16; + CyclicBarrier barrier = new CyclicBarrier(count); + ExecutorService pool = Executors.newFixedThreadPool(count); + try { + List> futures = new ArrayList<>(); + for (int i = 0; i < count; i++) { + int index = i; + futures.add(pool.submit(() -> { + EmailBuilder email = template.to("user" + index + "@example.com"); + barrier.await(); + email = email.html("

" + index + "

"); + barrier.await(); + return email.send(SendOptions.idempotencyKey("key-" + index)); + })); + } + for (Future future : futures) { + future.get(); + } + } finally { + pool.shutdown(); + } + assertEquals(count, server.requests().size()); + for (FakeServer.Request request : server.requests()) { + JsonNode body = JSON.readTree(request.body()); + String index = body.get("to").get(0).asText().replaceAll("\\D", ""); + assertEquals("

" + index + "

", body.get("html").asText()); + assertEquals("key-" + index, request.header("idempotency-key")); + } + } + + @Test + void validatesTags() { + EmailMessage base = EmailMessage.create(); + List twenty = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + twenty.add(new MessageTagInput("t" + i, "v")); + } + base.tags(twenty); + List twentyOne = new ArrayList<>(twenty); + twentyOne.add(new MessageTagInput("t20", "v")); + assertEquals("No more than 20 message tags are permitted.", + assertThrows(LettermintValidationException.class, () -> base.tags(twentyOne)).getMessage()); + assertEquals("A legacy tag and no more than 19 message tags are permitted.", + assertThrows(LettermintValidationException.class, () -> base.tags(twenty).tag("legacy")).getMessage()); + assertEquals("A legacy tag and no more than 19 message tags are permitted.", + assertThrows(LettermintValidationException.class, () -> base.tag("legacy").tags(twenty)).getMessage()); + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput("x".repeat(33), "v"))); + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput("a", "v".repeat(65)))); + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput("a", ""))); + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput("a b", "v"))); + assertEquals("Message tag names must not start with __lettermint.", + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput("__LetterMint_x", "v"))).getMessage()); + LettermintValidationException duplicate = assertThrows(LettermintValidationException.class, + () -> base.tags(new MessageTagInput("a", "1"), new MessageTagInput("a", "2"))); + assertEquals("tags", duplicate.getField()); + base.tags(new MessageTagInput("a", "1"), new MessageTagInput("A", "2")); + assertThrows(LettermintValidationException.class, () -> base.tags(new MessageTagInput(null, "1"))); + assertTrue(server.requests().isEmpty()); + } + + @Test + void validatesAttachments() { + assertThrows(LettermintValidationException.class, () -> EmailAttachment.of("", new byte[] {1})); + assertThrows(LettermintValidationException.class, () -> EmailAttachment.of("a.txt", null)); + assertThrows(LettermintValidationException.class, () -> EmailAttachment.ofBase64(null, "AA==")); + byte[] bytes = {1, 2, 3}; + EmailAttachment attachment = EmailAttachment.of("a.bin", bytes); + bytes[0] = 9; + assertEquals("AQID", attachment.base64Content()); + assertEquals("EmailAttachment{filename=a.bin}", attachment.toString()); + } + + @Test + void sendsBatches() throws Exception { + EmailBuilder welcome = client.emails().compose().from("hello@acme.com").subject("Welcome"); + List results = client.emails().sendBatch(List.of( + EmailMessage.create().from("a@b.c").to("d@e.f").subject("One").text("1"), + welcome.to("john@example.com").html("

2

").build()), SendOptions.idempotencyKey("batch-1")); + assertEquals(2, results.size()); + assertEquals("scheduled", results.get(1).status().value()); + assertEquals("/v1/send/batch", server.last().path()); + assertEquals("batch-1", server.last().header("idempotency-key")); + JsonNode body = lastBody(); + assertEquals(2, body.size()); + assertEquals("Welcome", body.get(1).get("subject").asText()); + + List withNull = new ArrayList<>(); + withNull.add(null); + assertEquals("messages[0]", assertThrows(LettermintValidationException.class, () -> client.emails().sendBatch(withNull)).getField()); + assertThrows(LettermintValidationException.class, () -> client.emails().sendBatch(null)); + } + + @Test + void reschedulesFromAString() throws Exception { + client.emails().send(EmailMessage.create().from("a@b.c").scheduledAt("tomorrow 9am")); + assertEquals("tomorrow 9am", lastBody().get("scheduled_at").asText()); + client.emails().send(EmailMessage.create().from("a@b.c").scheduledAt("tomorrow").scheduledAt((String) null)); + assertNull(lastBody().get("scheduled_at")); + } + + @Test + void toStringShowsTheMessageWithoutContent() { + EmailBuilder builder = client.emails().compose().from("a@b.c").to("d@e.f").html("

secret html

") + .attach(EmailAttachment.ofBase64("a.txt", "c2VjcmV0")); + String text = builder.toString(); + assertTrue(text.startsWith("EmailBuilder{EmailMessage{from=a@b.c, to=[d@e.f], html=(18 characters)"), text); + assertTrue(!text.contains("c2VjcmV0") && !text.contains("secret html"), text); + assertEquals("Emails{}", client.emails().toString()); + } +} diff --git a/src/test/java/co/lettermint/FakeServer.java b/src/test/java/co/lettermint/FakeServer.java new file mode 100644 index 0000000..d159d0c --- /dev/null +++ b/src/test/java/co/lettermint/FakeServer.java @@ -0,0 +1,158 @@ +package co.lettermint; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Deque; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Executors; +import java.util.function.Function; + +/** A local HTTP server that records requests and answers with queued or default responses. */ +final class FakeServer implements AutoCloseable { + /** A recorded request. Header names are lower-case. */ + record Request(String method, String path, String rawQuery, Map> headers, String body) { + String header(String name) { + List values = headers.get(name.toLowerCase()); + return values == null || values.isEmpty() ? null : values.get(0); + } + + String target() { + return path + (rawQuery == null ? "" : "?" + rawQuery); + } + } + + /** A response: status, headers, body, and an optional delay before the body. */ + record Response(int status, Map headers, String body, long delayMillis, boolean stallBody) { + static Response json(int status, String body) { + return new Response(status, Map.of("Content-Type", "application/json"), body, 0, false); + } + + static Response text(int status, String contentType, String body) { + return new Response(status, contentType == null ? Map.of() : Map.of("Content-Type", contentType), body, 0, false); + } + + static Response empty(int status) { + return new Response(status, Map.of(), null, 0, false); + } + + Response header(String name, String value) { + Map next = new LinkedHashMap<>(headers); + next.put(name, value); + return new Response(status, next, body, delayMillis, stallBody); + } + + Response delay(long millis) { + return new Response(status, headers, body, millis, stallBody); + } + + /** Sends the headers at once and then waits {@code delay} before the body. */ + Response stallBody(long millis) { + return new Response(status, headers, body, millis, true); + } + } + + private final HttpServer server; + private final List requests = Collections.synchronizedList(new ArrayList<>()); + private final Deque queue = new ArrayDeque<>(); + private volatile Function fallback = request -> Response.json(200, "{}"); + + FakeServer() throws IOException { + server = HttpServer.create(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), 0); + server.setExecutor(Executors.newCachedThreadPool()); + server.createContext("/", this::handle); + server.start(); + } + + String origin() { + return "http://127.0.0.1:" + server.getAddress().getPort(); + } + + String baseUrl() { + return origin() + "/v1"; + } + + /** Answers the next request with {@code response}; later requests use the fallback. */ + synchronized FakeServer enqueue(Response response) { + queue.add(response); + return this; + } + + FakeServer fallback(Function fallback) { + this.fallback = fallback; + return this; + } + + List requests() { + synchronized (requests) { + return List.copyOf(requests); + } + } + + Request last() { + List all = requests(); + return all.get(all.size() - 1); + } + + private synchronized Response next(Request request) { + Response queued = queue.poll(); + return queued != null ? queued : fallback.apply(request); + } + + private void handle(HttpExchange exchange) throws IOException { + URI uri = exchange.getRequestURI(); + Map> headers = new LinkedHashMap<>(); + exchange.getRequestHeaders().forEach((name, values) -> headers.put(name.toLowerCase(), List.copyOf(values))); + String body; + try (InputStream in = exchange.getRequestBody()) { + body = new String(in.readAllBytes(), StandardCharsets.UTF_8); + } + Request request = new Request(exchange.getRequestMethod(), uri.getRawPath(), uri.getRawQuery(), headers, body); + requests.add(request); + Response response = next(request); + try { + if (response.delayMillis() > 0 && !response.stallBody()) { + Thread.sleep(response.delayMillis()); + } + response.headers().forEach((name, value) -> exchange.getResponseHeaders().add(name, value)); + byte[] bytes = response.body() == null ? new byte[0] : response.body().getBytes(StandardCharsets.UTF_8); + if (response.stallBody()) { + exchange.sendResponseHeaders(response.status(), bytes.length + 1L); + try (OutputStream out = exchange.getResponseBody()) { + out.write(bytes); + out.flush(); + Thread.sleep(response.delayMillis()); + out.write(' '); + } + return; + } + boolean noBody = response.status() == 204 || response.status() == 304 || bytes.length == 0; + exchange.sendResponseHeaders(response.status(), noBody ? -1 : bytes.length); + if (!noBody) { + try (OutputStream out = exchange.getResponseBody()) { + out.write(bytes); + } + } + } catch (InterruptedException | IOException error) { + Thread.currentThread().interrupt(); + } finally { + exchange.close(); + } + } + + @Override + public void close() { + server.stop(0); + } +} diff --git a/src/test/java/co/lettermint/LettermintTest.java b/src/test/java/co/lettermint/LettermintTest.java deleted file mode 100644 index 9df8c55..0000000 --- a/src/test/java/co/lettermint/LettermintTest.java +++ /dev/null @@ -1,39 +0,0 @@ -package co.lettermint; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class LettermintTest { - - @Test - void testCreateWithToken() { - Lettermint lettermint = new Lettermint("test-token"); - assertNotNull(lettermint); - assertNotNull(lettermint.email()); - assertNotNull(lettermint.getClient()); - } - - @Test - void testCreateWithCustomBaseUrl() { - Lettermint lettermint = new Lettermint("test-token", "https://custom.api.com/v1"); - assertNotNull(lettermint); - } - - @Test - void testCreateWithNullToken() { - assertThrows(IllegalArgumentException.class, () -> new Lettermint(null)); - } - - @Test - void testCreateWithEmptyToken() { - assertThrows(IllegalArgumentException.class, () -> new Lettermint("")); - } - - @Test - void testEmailEndpointIsNewInstanceForThreadSafety() { - Lettermint lettermint = new Lettermint("test-token"); - // Each call returns a new instance to ensure thread-safety - assertNotSame(lettermint.email(), lettermint.email()); - } -} diff --git a/src/test/java/co/lettermint/OkHttpCompatibilityTest.java b/src/test/java/co/lettermint/OkHttpCompatibilityTest.java deleted file mode 100644 index d3866c9..0000000 --- a/src/test/java/co/lettermint/OkHttpCompatibilityTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package co.lettermint; - -import co.lettermint.models.SendEmailResponse; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import okio.ByteString; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.IOException; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * Verifies OkHttp/Okio compatibility after downgrade to 4.9.3. - * Exercises ByteString and request/response serialization paths - * that previously caused NoSuchFieldError with Okio 3.x. - */ -class OkHttpCompatibilityTest { - - private MockWebServer server; - private Lettermint lettermint; - - @BeforeEach - void setUp() throws IOException { - server = new MockWebServer(); - server.start(); - lettermint = new Lettermint("test-token", server.url("/v1").toString()); - } - - @AfterEach - void tearDown() throws IOException { - server.shutdown(); - } - - @Test - void okioByteStringIsAccessible() { - // This is the exact code path that fails with NoSuchFieldError - // when Okio 2.x and 3.x jars conflict on the classpath - ByteString bs = ByteString.encodeUtf8("hello"); - assertEquals("hello", bs.utf8()); - } - - @Test - void fullRoundTripRequest() throws Exception { - server.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_compat\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - - SendEmailResponse response = lettermint.email() - .from("test@example.com") - .to("recipient@example.com") - .subject("OkHttp 4.9.3 compat test") - .text("Verifying request body serialization through Okio") - .html("

With HTML body too

") - .send(); - - assertEquals("msg_compat", response.getMessageId()); - assertEquals("queued", response.getStatus()); - - RecordedRequest recorded = server.takeRequest(); - assertEquals("POST", recorded.getMethod()); - - // readUtf8() goes through Okio's Buffer/ByteString internally - String body = recorded.getBody().readUtf8(); - assertTrue(body.contains("\"subject\":\"OkHttp 4.9.3 compat test\"")); - assertTrue(body.contains("\"text\":\"Verifying request body serialization through Okio\"")); - assertTrue(body.contains("\"html\":\"

With HTML body too

\"")); - } - - @Test - void multipleSequentialRequests() throws Exception { - for (int i = 0; i < 3; i++) { - server.enqueue(new MockResponse() - .setBody("{\"message_id\": \"msg_" + i + "\", \"status\": \"queued\"}") - .setHeader("Content-Type", "application/json")); - } - - for (int i = 0; i < 3; i++) { - SendEmailResponse response = lettermint.email() - .from("test@example.com") - .to("r@example.com") - .subject("Msg " + i) - .text("Body " + i) - .send(); - - assertEquals("msg_" + i, response.getMessageId()); - } - - // Verify all 3 requests went through with correct bodies - for (int i = 0; i < 3; i++) { - RecordedRequest req = server.takeRequest(); - String body = req.getBody().readUtf8(); - assertTrue(body.contains("\"subject\":\"Msg " + i + "\"")); - } - } -} diff --git a/src/test/java/co/lettermint/TeamApiTest.java b/src/test/java/co/lettermint/TeamApiTest.java new file mode 100644 index 0000000..8f13666 --- /dev/null +++ b/src/test/java/co/lettermint/TeamApiTest.java @@ -0,0 +1,265 @@ +package co.lettermint; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import co.lettermint.exceptions.NotFoundException; +import co.lettermint.exceptions.UnexpectedResponseException; +import co.lettermint.types.AnalyticsMetric; +import co.lettermint.types.AnalyticsQuery; +import co.lettermint.types.CursorPage; +import co.lettermint.types.DomainListData; +import co.lettermint.types.GetStatsQuery; +import co.lettermint.types.ListDomainsQuery; +import co.lettermint.types.ListWebhookDeliveriesQuery; +import co.lettermint.types.Operations; +import co.lettermint.types.ProjectAccessScope; +import co.lettermint.types.ReportForwardingRequest; +import co.lettermint.types.RescheduleMessageRequest; +import co.lettermint.types.RouteType; +import co.lettermint.types.StoreDomainData; +import co.lettermint.types.StoreProjectData; +import co.lettermint.types.StoreRouteData; +import co.lettermint.types.StoreSuppressionData; +import co.lettermint.types.StoreWebhookData; +import co.lettermint.types.SuppressionCreateReason; +import co.lettermint.types.SuppressionCreateScope; +import co.lettermint.types.UpdateDomainProjectsData; +import co.lettermint.types.UpdateProjectData; +import co.lettermint.types.UpdateRouteData; +import co.lettermint.types.UpdateTeamData; +import co.lettermint.types.UpdateTeamMemberAssignmentData; +import co.lettermint.types.UpdateTeamMemberAssignmentDataProjectAccess; +import co.lettermint.types.UpdateWebhookData; +import co.lettermint.types.VerifyReportForwardingRequest; +import co.lettermint.types.WebhookEvent; +import co.lettermint.types.WebhookListData; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TeamApiTest { + private FakeServer server; + private Lettermint client; + + @BeforeEach + void start() throws Exception { + server = new FakeServer(); + client = Lettermint.builder().sendingToken(ClientTest.SENDING).teamToken(ClientTest.TEAM).baseUrl(server.baseUrl()).build(); + } + + @AfterEach + void stop() { + server.close(); + } + + private static String page(String cursor, String... ids) { + String data = List.of(ids).stream().map(id -> "{\"id\":\"" + id + "\"}").collect(Collectors.joining(",")); + return "{\"data\":[" + data + "],\"path\":null,\"per_page\":2,\"next_cursor\":" + (cursor == null ? "null" : "\"" + cursor + "\"") + + ",\"next_page_url\":null,\"prev_cursor\":null,\"prev_page_url\":null}"; + } + + /** Maps a recorded request back to its operation key by matching the path templates. */ + private static String operationKey(FakeServer.Request request) { + String best = request.method() + " " + request.path(); + int fewest = Integer.MAX_VALUE; + for (Operations.Operation operation : Operations.ALL.values()) { + String pattern = "/v1" + operation.path().replaceAll("\\{\\w+}", "[^/]+"); + // Prefer literal segments over placeholders, e.g. /send/batch is not /send/{x}. + if (operation.method().equals(request.method()) && request.path().matches(pattern) && operation.pathParams().size() < fewest) { + best = operation.key(); + fewest = operation.pathParams().size(); + } + } + return best; + } + + @SuppressWarnings("deprecation") + private void rotateToken(String projectId) { + client.projects().rotateToken(projectId); + } + + @Test + void everyOperationIsReachable() { + server.fallback(request -> { + String key = operationKey(request); + if (key.equals("GET /ping") || key.endsWith("/html") || key.endsWith("/text") || key.endsWith("/source")) { + return FakeServer.Response.text(200, "text/plain", "pong"); + } + if (key.equals("DELETE /projects/{projectId}/report-forwarding")) { + return FakeServer.Response.empty(204); + } + Operations.Operation operation = Operations.ALL.get(key); + if (operation != null && operation.pagination() != null) { + return FakeServer.Response.json(200, page(null, "x")); + } + if (key.equals("POST /send/batch")) { + return FakeServer.Response.json(202, "[]"); + } + return FakeServer.Response.json(200, "{}"); + }); + EmailMessage email = EmailMessage.create().from("a@b.c").to("d@e.f").subject("s"); + List calls = List.of( + () -> client.ping(), + () -> client.analytics(AnalyticsQuery.builder().metrics(List.of(AnalyticsMetric.of("sent"))).build()), + () -> client.blockedFileTypes(), + () -> client.emails().send(email), + () -> client.emails().sendBatch(List.of(email)), + () -> client.domains().list(), + () -> client.domains().iterate().forEach(item -> { }), + () -> client.domains().create(new StoreDomainData("acme.com")), + () -> client.domains().retrieve("d1"), + () -> client.domains().delete("d1"), + () -> client.domains().verifyDnsRecords("d1"), + () -> client.domains().verifyDnsRecord("d1", "r1"), + () -> client.domains().updateProjects("d1", new UpdateDomainProjectsData(List.of("p1"))), + () -> client.messages().list(), + () -> client.messages().iterate().forEach(item -> { }), + () -> client.messages().retrieve("m1"), + () -> client.messages().events("m1"), + () -> client.messages().iterateEvents("m1").forEach(item -> { }), + () -> client.messages().source("m1"), + () -> client.messages().html("m1"), + () -> client.messages().text("m1"), + () -> client.messages().reschedule("m1", new RescheduleMessageRequest("2026-10-20T09:00:00Z")), + () -> client.messages().cancel("m1"), + () -> client.messages().process("m1"), + () -> client.projects().list(), + () -> client.projects().iterate().forEach(item -> { }), + () -> client.projects().create(StoreProjectData.builder().name("Production").build()), + () -> client.projects().retrieve("p1"), + () -> client.projects().update("p1", UpdateProjectData.builder().name("Renamed").build()), + () -> client.projects().delete("p1"), + () -> rotateToken("p1"), + () -> client.projects().reportForwarding().retrieve("p1"), + () -> client.projects().reportForwarding().update("p1", new ReportForwardingRequest("dmarc@acme.com")), + () -> client.projects().reportForwarding().delete("p1"), + () -> client.projects().reportForwarding().verify("p1", new VerifyReportForwardingRequest("123456")), + () -> client.projects().reportForwarding().resendCode("p1"), + () -> client.routes().list("p1"), + () -> client.routes().iterate("p1").forEach(item -> { }), + () -> client.routes().create("p1", StoreRouteData.builder().name("Inbound").routeType(RouteType.of("inbound")).build()), + () -> client.routes().retrieve("r1"), + () -> client.routes().update("r1", UpdateRouteData.builder().name("New").build()), + () -> client.routes().delete("r1"), + () -> client.routes().verifyInboundDomain("r1"), + () -> client.stats().retrieve(GetStatsQuery.builder().from("2026-10-01").to("2026-10-31").build()), + () -> client.suppressions().list(), + () -> client.suppressions().iterate().forEach(item -> { }), + () -> client.suppressions().create(StoreSuppressionData.builder().email("a@b.c") + .reason(SuppressionCreateReason.of("manual")).scope(SuppressionCreateScope.of("team")).build()), + () -> client.suppressions().delete("s1"), + () -> client.team().retrieve(), + () -> client.team().update(UpdateTeamData.builder().name("Acme").build()), + () -> client.team().usage(), + () -> client.team().roles(), + () -> client.team().members().list(), + () -> client.team().members().iterate().forEach(item -> { }), + () -> client.team().members().retrieve("u1"), + () -> client.team().members().updateAssignment("u1", new UpdateTeamMemberAssignmentData("role1", + new UpdateTeamMemberAssignmentDataProjectAccess(ProjectAccessScope.of("all"), null))), + () -> client.webhooks().list(), + () -> client.webhooks().iterate().forEach(item -> { }), + () -> client.webhooks().create(StoreWebhookData.builder().name("Hook").url("https://acme.com/hook") + .events(List.of(WebhookEvent.MESSAGE_DELIVERED)).build()), + () -> client.webhooks().retrieve("w1"), + () -> client.webhooks().update("w1", UpdateWebhookData.builder().enabled(false).build()), + () -> client.webhooks().delete("w1"), + () -> client.webhooks().test("w1"), + () -> client.webhooks().regenerateSecret("w1"), + () -> client.webhooks().deliveries().list("w1"), + () -> client.webhooks().deliveries().iterate("w1").forEach(item -> { }), + () -> client.webhooks().deliveries().retrieve("w1", "dl1")); + calls.forEach(Runnable::run); + + Set reached = new TreeSet<>(); + for (FakeServer.Request request : server.requests()) { + reached.add(operationKey(request)); + } + assertEquals(new TreeSet<>(Operations.ALL.keySet()), reached); + } + + @Test + void teamCallsUseTheBearerToken() { + client.domains().create(new StoreDomainData("acme.com")); + assertEquals("POST", server.last().method()); + assertEquals("/v1/domains", server.last().path()); + assertEquals("Bearer " + ClientTest.TEAM, server.last().header("authorization")); + assertNull(server.last().header("x-lettermint-token")); + assertEquals("{\"domain\":\"acme.com\"}", server.last().body()); + } + + @Test + void updatesSendExplicitNulls() { + client.routes().update("r1", UpdateRouteData.builder().inboundDomain(null).name("Main").build()); + assertEquals("PUT", server.last().method()); + assertEquals("{\"name\":\"Main\",\"inbound_domain\":null}", server.last().body()); + } + + @Test + void listsReturnTypedPages() { + server.enqueue(FakeServer.Response.json(200, page("c2", "d1", "d2"))); + CursorPage first = client.domains().list(ListDomainsQuery.builder().pageSize(2).build()); + assertEquals(List.of("d1", "d2"), first.data().stream().map(DomainListData::id).toList()); + assertEquals("c2", first.nextCursor()); + assertTrue(first.hasNextPage()); + assertEquals(2L, first.perPage()); + } + + @Test + void iterateFollowsTheCursor() { + server.enqueue(FakeServer.Response.json(200, page("c2", "d1", "d2"))); + server.enqueue(FakeServer.Response.json(200, page("c3", "d3"))); + server.enqueue(FakeServer.Response.json(200, page(null, "d4"))); + CursorIterable domains = client.domains().iterate(ListDomainsQuery.builder().pageSize(2).build()); + assertTrue(server.requests().isEmpty(), "iterate() is lazy"); + List ids = new ArrayList<>(); + for (DomainListData domain : domains) { + ids.add(domain.id()); + } + assertEquals(List.of("d1", "d2", "d3", "d4"), ids); + List queries = server.requests().stream().map(FakeServer.Request::rawQuery).toList(); + assertEquals(List.of("page%5Bsize%5D=2", "page%5Bsize%5D=2&page%5Bcursor%5D=c2", "page%5Bsize%5D=2&page%5Bcursor%5D=c3"), queries); + } + + @Test + void iterateUsesTheOperationsCursorParameterAndStopsOnARepeatedCursor() { + server.enqueue(FakeServer.Response.json(200, page("same", "w1"))); + server.enqueue(FakeServer.Response.json(200, page("same", "w2"))); + server.enqueue(FakeServer.Response.json(200, page("never", "w3"))); + List ids = client.webhooks().iterate().stream().map(WebhookListData::id).toList(); + assertEquals(List.of("w1", "w2"), ids); + assertEquals("cursor=same", server.requests().get(1).rawQuery()); + assertEquals(2, server.requests().size()); + + server.enqueue(FakeServer.Response.json(200, page("c2", "dl1"))); + server.enqueue(FakeServer.Response.json(200, page(null, "dl2"))); + client.webhooks().deliveries().iterate("w1", ListWebhookDeliveriesQuery.builder().filterEventType("message.delivered").build()) + .forEach(item -> { }); + assertEquals("filter%5Bevent_type%5D=message.delivered&cursor=c2", server.last().rawQuery()); + } + + @Test + void streamsStopEarly() { + server.enqueue(FakeServer.Response.json(200, page("c2", "d1", "d2"))); + server.enqueue(FakeServer.Response.json(200, page(null, "d3"))); + assertEquals(List.of("d1"), client.domains().iterate().stream().limit(1).map(DomainListData::id).toList()); + assertEquals(1, server.requests().size()); + } + + @Test + void iterateReportsBadPagesAndErrors() { + server.enqueue(FakeServer.Response.json(200, "{\"next_cursor\":null}")); + UnexpectedResponseException bad = assertThrows(UnexpectedResponseException.class, () -> client.domains().iterate().iterator().hasNext()); + assertTrue(bad.getMessage().startsWith("domains.iterate: the API returned a page without a data array.")); + server.enqueue(FakeServer.Response.json(404, "{\"message\":\"Not found\"}")); + assertThrows(NotFoundException.class, () -> client.routes().iterate("p1").iterator().next()); + } +} diff --git a/src/test/java/co/lettermint/TransportTest.java b/src/test/java/co/lettermint/TransportTest.java new file mode 100644 index 0000000..c8a4ef6 --- /dev/null +++ b/src/test/java/co/lettermint/TransportTest.java @@ -0,0 +1,295 @@ +package co.lettermint; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import co.lettermint.exceptions.ApiException; +import co.lettermint.exceptions.AuthenticationException; +import co.lettermint.exceptions.ConflictException; +import co.lettermint.exceptions.ConnectionException; +import co.lettermint.exceptions.LettermintConfigException; +import co.lettermint.exceptions.LettermintException; +import co.lettermint.exceptions.LettermintValidationException; +import co.lettermint.exceptions.NotFoundException; +import co.lettermint.exceptions.PermissionException; +import co.lettermint.exceptions.RateLimitException; +import co.lettermint.exceptions.RedirectException; +import co.lettermint.exceptions.ServerException; +import co.lettermint.exceptions.TimeoutException; +import co.lettermint.exceptions.UnexpectedResponseException; +import co.lettermint.exceptions.ValidationException; +import co.lettermint.types.DomainStatus; +import co.lettermint.types.GetDomainQueryIncludeItem; +import co.lettermint.types.GetDomainQuery; +import co.lettermint.types.ListDomainsQuery; +import co.lettermint.types.ListDomainsQuerySortItem; +import co.lettermint.types.ListMessagesQuery; +import co.lettermint.types.ListMessagesQueryFilter; +import co.lettermint.types.ListMessagesQueryFilterTagsItem; +import co.lettermint.types.ListWebhooksQuery; +import co.lettermint.types.MessageStatus; +import co.lettermint.types.SendMailResponse; +import java.net.ServerSocket; +import java.time.Duration; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CancellationException; +import java.util.concurrent.atomic.AtomicReference; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class TransportTest { + private FakeServer server; + private Lettermint client; + + @BeforeEach + void start() throws Exception { + server = new FakeServer(); + client = Lettermint.builder().sendingToken(ClientTest.SENDING).teamToken(ClientTest.TEAM).baseUrl(server.baseUrl()).build(); + } + + @AfterEach + void stop() { + server.close(); + } + + private SendMailResponse send() { + return client.emails().send(EmailMessage.create().from("a@example.com").to("b@example.com").subject("Hi").text("Hello")); + } + + @Test + void decodesUnknownEnumsAndFields() { + server.enqueue(FakeServer.Response.json(202, "{\"message_id\":\"m1\",\"status\":\"some_future_status\",\"some_future_field\":{\"nested\":[1]}}")); + SendMailResponse response = send(); + assertEquals("m1", response.messageId()); + assertEquals("some_future_status", response.status().value()); + server.enqueue(FakeServer.Response.json(202, "{\"message_id\":\"m2\",\"status\":\"pending\"}")); + assertEquals(MessageStatus.PENDING, send().status()); + } + + @Test + void emptyAndInvalidBodiesAreUnexpectedResponses() { + server.enqueue(FakeServer.Response.text(202, "application/json", "")); + UnexpectedResponseException empty = assertThrows(UnexpectedResponseException.class, this::send); + assertEquals(202, empty.getStatus()); + server.enqueue(FakeServer.Response.text(200, "application/json", "not json")); + assertEquals(200, assertThrows(UnexpectedResponseException.class, this::send).getStatus()); + server.enqueue(FakeServer.Response.json(200, "[1,2]")); + assertEquals(200, assertThrows(UnexpectedResponseException.class, this::send).getStatus()); + String html = "502 Bad Gateway" + "x".repeat(300) + ""; + server.enqueue(FakeServer.Response.text(502, "text/html; charset=UTF-8", html)); + UnexpectedResponseException page = assertThrows(UnexpectedResponseException.class, this::send); + assertEquals(502, page.getStatus()); + assertTrue(page.getMessage().contains("(text/html)"), page.getMessage()); + assertEquals(201, page.getBodyExcerpt().length()); + server.enqueue(FakeServer.Response.empty(304)); + assertThrows(RedirectException.class, this::send); + } + + @Test + void mapsErrorStatuses() { + Map> expected = Map.of(400, ApiException.class, 401, AuthenticationException.class, 403, PermissionException.class, + 404, NotFoundException.class, 409, ConflictException.class, 422, ValidationException.class, 429, RateLimitException.class, + 500, ServerException.class, 503, ServerException.class); + for (Map.Entry> entry : expected.entrySet()) { + server.enqueue(FakeServer.Response.json(entry.getKey(), "{\"error\":{\"code\":\"E_CODE\",\"message\":\"Nope\",\"details\":{\"a\":1}}}")); + ApiException error = assertThrows(ApiException.class, this::send); + assertEquals(entry.getValue(), error.getClass()); + assertEquals(entry.getKey(), error.getStatus()); + assertEquals("E_CODE", error.getCode()); + assertEquals("Nope", error.getMessage()); + assertEquals(Map.of("a", 1), error.getDetails()); + } + server.enqueue(FakeServer.Response.json(422, "{\"message\":\"The to field is required.\",\"errors\":{\"to\":[\"The to field is required.\"]}}")); + ValidationException validation = assertThrows(ValidationException.class, this::send); + assertEquals("The to field is required.", validation.getMessage()); + assertEquals(Map.of("to", List.of("The to field is required.")), validation.getErrors()); + assertNull(validation.getCode()); + + server.enqueue(FakeServer.Response.json(403, "{\"error\":\"plan_required\",\"message\":\"Upgrade\"}")); + PermissionException permission = assertThrows(PermissionException.class, this::send); + assertEquals("plan_required", permission.getCode()); + assertEquals("Upgrade", permission.getMessage()); + + server.enqueue(FakeServer.Response.empty(500)); + ServerException empty = assertThrows(ServerException.class, this::send); + assertEquals("HTTP 500", empty.getMessage()); + assertNull(empty.getBody()); + + server.enqueue(FakeServer.Response.json(429, "{\"message\":\"Slow down\"}").header("Retry-After", "7")); + assertEquals(Duration.ofSeconds(7), assertThrows(RateLimitException.class, this::send).getRetryAfter()); + String date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now().plusSeconds(30)); + server.enqueue(FakeServer.Response.json(429, "{}").header("Retry-After", date)); + long seconds = assertThrows(RateLimitException.class, this::send).getRetryAfter().getSeconds(); + assertTrue(seconds > 20 && seconds <= 31, String.valueOf(seconds)); + server.enqueue(FakeServer.Response.json(429, "{}")); + assertNull(assertThrows(RateLimitException.class, this::send).getRetryAfter()); + } + + @Test + void neverFollowsRedirects() throws Exception { + try (FakeServer foreign = new FakeServer()) { + server.enqueue(FakeServer.Response.json(307, "{\"message\":\"Moved\"}").header("Location", foreign.baseUrl() + "/send")); + RedirectException error = assertThrows(RedirectException.class, this::send); + assertEquals(307, error.getStatus()); + server.enqueue(FakeServer.Response.empty(302).header("Location", foreign.baseUrl() + "/ping")); + assertThrows(RedirectException.class, () -> client.ping()); + assertTrue(foreign.requests().isEmpty()); + } + } + + @Test + void doesNotRetry() { + server.enqueue(FakeServer.Response.json(500, "{}")); + assertThrows(ServerException.class, this::send); + assertEquals(1, server.requests().size()); + } + + @Test + void theTimeoutCoversTheBody() { + Lettermint fast = Lettermint.builder().sendingToken(ClientTest.SENDING).baseUrl(server.baseUrl()).timeout(Duration.ofMillis(300)).build(); + server.enqueue(FakeServer.Response.json(202, "{\"message_id\":\"m\",\"status\":\"pending\"}").stallBody(3000)); + long started = System.nanoTime(); + TimeoutException error = assertThrows(TimeoutException.class, + () -> fast.emails().send(EmailMessage.create().from("a@b.c").to("d@e.f").subject("s"))); + assertTrue(System.nanoTime() - started < 2_500_000_000L); + assertEquals(Duration.ofMillis(300), error.getTimeout()); + + server.enqueue(FakeServer.Response.json(202, "{}").delay(3000)); + assertThrows(TimeoutException.class, () -> client.emails().send(EmailMessage.create().from("a@b.c"), + SendOptions.timeout(Duration.ofMillis(200)))); + server.enqueue(FakeServer.Response.json(200, "{}").delay(3000)); + assertThrows(TimeoutException.class, () -> client.domains().list(null, RequestOptions.timeout(Duration.ofMillis(200)))); + assertThrows(LettermintConfigException.class, () -> client.domains().list(null, RequestOptions.timeout(Duration.ZERO))); + } + + @Test + void connectionFailuresAreTyped() throws Exception { + int port; + try (ServerSocket socket = new ServerSocket(0)) { + port = socket.getLocalPort(); + } + Lettermint unreachable = Lettermint.builder().teamToken(ClientTest.TEAM).baseUrl("http://127.0.0.1:" + port + "/v1").build(); + LettermintException error = assertThrows(LettermintException.class, unreachable::ping); + assertInstanceOf(ConnectionException.class, error); + assertTrue(error.getMessage().startsWith("Could not reach the Lettermint API")); + } + + @Test + void interruptingTheThreadCancelsTheRequest() throws Exception { + server.enqueue(FakeServer.Response.json(200, "{}").delay(5000)); + AtomicReference thrown = new AtomicReference<>(); + AtomicReference interrupted = new AtomicReference<>(); + Thread thread = new Thread(() -> { + try { + client.domains().list(); + } catch (Throwable error) { + thrown.set(error); + interrupted.set(Thread.currentThread().isInterrupted()); + } + }); + thread.start(); + while (server.requests().isEmpty()) { + Thread.sleep(10); + } + thread.interrupt(); + thread.join(3000); + assertInstanceOf(CancellationException.class, thrown.get()); + assertTrue(interrupted.get()); + } + + @Test + void encodesAndChecksPathParameters() { + client.domains().retrieve("a b/c?d#é"); + assertEquals("/v1/domains/a%20b%2Fc%3Fd%23%C3%A9", server.last().path()); + client.webhooks().deliveries().retrieve("wh!*'()", "d~._-"); + assertEquals("/v1/webhooks/wh!*'()/deliveries/d~._-", server.last().path()); + int before = server.requests().size(); + for (String invalid : new String[] {"", ".", "..", null}) { + LettermintConfigException error = assertThrows(LettermintConfigException.class, () -> client.domains().delete(invalid)); + assertEquals("domains.delete: domainId must be a non-empty string other than \".\" and \"..\".", error.getMessage()); + } + assertThrows(LettermintConfigException.class, () -> client.webhooks().deliveries().retrieve("wh", "..")); + assertEquals(before, server.requests().size()); + } + + @Test + void serializesQueriesLikeTheNodeSdk() { + client.domains().list(ListDomainsQuery.builder().pageSize(30).filterStatus(DomainStatus.VERIFIED) + .sort(List.of(ListDomainsQuerySortItem.CREATED_AT_DESC, ListDomainsQuerySortItem.DOMAIN)).build()); + assertEquals("page%5Bsize%5D=30&sort=-created_at%2Cdomain&filter%5Bstatus%5D=verified", server.last().rawQuery()); + + client.messages().list(ListMessagesQuery.builder() + .filter(ListMessagesQueryFilter.builder().tags(List.of( + ListMessagesQueryFilterTagsItem.builder().name("campaign").value("welcome").build(), + ListMessagesQueryFilterTagsItem.builder().name("plan").value("pro").build())).build()) + .filterSearch("hello world & more").filterStatus(MessageStatus.of("a_future_status")).build()); + assertEquals("filter%5Bsearch%5D=hello+world+%26+more" + + "&filter%5Btags%5D%5B0%5D%5Bname%5D=campaign&filter%5Btags%5D%5B0%5D%5Bvalue%5D=welcome" + + "&filter%5Btags%5D%5B1%5D%5Bname%5D=plan&filter%5Btags%5D%5B1%5D%5Bvalue%5D=pro" + + "&filter%5Bstatus%5D=a_future_status", server.last().rawQuery()); + + client.webhooks().list(ListWebhooksQuery.builder().filterEnabled(true).build()); + assertEquals("filter%5Benabled%5D=1", server.last().rawQuery()); + client.webhooks().list(ListWebhooksQuery.builder().filterEnabled(false).sort(List.of()).build()); + assertEquals("filter%5Benabled%5D=0", server.last().rawQuery()); + + client.domains().retrieve("d1", GetDomainQuery.builder().include(List.of(GetDomainQueryIncludeItem.DNS_RECORDS)).build()); + assertEquals("include=dnsRecords", server.last().rawQuery()); + client.domains().list(ListDomainsQuery.builder().build()); + assertNull(server.last().rawQuery()); + } + + @Test + void idempotencyKeysArePerCall() { + server.fallback(request -> FakeServer.Response.json(202, "{\"message_id\":\"m\",\"status\":\"pending\"}")); + EmailMessage message = EmailMessage.create().from("a@b.c").to("d@e.f").subject("s"); + client.emails().send(message, SendOptions.idempotencyKey("key-1")); + assertEquals("key-1", server.last().header("idempotency-key")); + client.emails().send(message); + assertNull(server.last().header("idempotency-key")); + client.messages().process("msg_1", SendOptions.idempotencyKey("process-1")); + assertEquals("process-1", server.last().header("idempotency-key")); + int before = server.requests().size(); + for (String invalid : new String[] {"", "a\nb", "a\rb", "a\u0000b"}) { + LettermintValidationException error = assertThrows(LettermintValidationException.class, + () -> client.emails().send(message, SendOptions.idempotencyKey(invalid))); + assertEquals("idempotencyKey", error.getField()); + } + assertEquals(before, server.requests().size()); + } + + @Test + void handlesEmptyAndTextResponses() { + server.enqueue(FakeServer.Response.empty(204)); + client.projects().reportForwarding().delete("p1"); + assertEquals("DELETE", server.last().method()); + server.enqueue(FakeServer.Response.text(200, "text/html; charset=UTF-8", "

Hi

\n")); + assertEquals("

Hi

\n", client.messages().html("m1")); + server.enqueue(FakeServer.Response.text(200, "message/rfc822", "Subject: x\r\n\r\nbody")); + assertEquals("Subject: x\r\n\r\nbody", client.messages().source("m1")); + server.enqueue(FakeServer.Response.text(200, "text/plain", "plain")); + assertEquals("plain", client.messages().text("m1")); + server.enqueue(FakeServer.Response.text(200, "text/html", " pong \n")); + assertEquals("pong", client.ping()); + } + + @Test + void requestBodiesAreJson() { + server.fallback(request -> FakeServer.Response.json(202, "{\"message_id\":\"m\",\"status\":\"pending\"}")); + send(); + assertEquals("POST", server.last().method()); + assertEquals("/v1/send", server.last().path()); + assertTrue(server.last().header("content-type").startsWith("application/json")); + assertEquals("{\"from\":\"a@example.com\",\"to\":[\"b@example.com\"],\"subject\":\"Hi\",\"text\":\"Hello\"}", server.last().body()); + client.domains().verifyDnsRecords("d1"); + assertNull(server.last().header("content-type")); + assertEquals("", server.last().body()); + } +} diff --git a/src/test/java/co/lettermint/WebhookBasicAuthTest.java b/src/test/java/co/lettermint/WebhookBasicAuthTest.java deleted file mode 100644 index 4d09c7e..0000000 --- a/src/test/java/co/lettermint/WebhookBasicAuthTest.java +++ /dev/null @@ -1,59 +0,0 @@ -package co.lettermint; - -import co.lettermint.api.ApiClient; -import co.lettermint.models.api.*; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import okhttp3.mockwebserver.MockResponse; -import okhttp3.mockwebserver.MockWebServer; -import okhttp3.mockwebserver.RecordedRequest; -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -class WebhookBasicAuthTest { - @Test - void createAndUpdatePreserveAllCredentialStatesAndBearerAuth() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - WebhookBasicAuthData credentials = new WebhookBasicAuthData(); - credentials.username = " fixture user "; - credentials.password = ""; - for (int state = 0; state < 3; state++) { - try (MockWebServer server = new MockWebServer()) { - for (int i = 0; i < 2; i++) server.enqueue(new MockResponse().setBody("{\"data\":{\"has_basic_auth\":true}}")); - server.start(); - ApiClient api = Lettermint.api("fixture-token", server.url("/v1").toString()); - StoreWebhookData create = new StoreWebhookData(); - create.name = "Fixture"; - create.url = "https://example.test/hook"; - UpdateWebhookData update = new UpdateWebhookData(); - if (state == 1) { create.basicAuth = OptionalNullable.of(credentials); update.basicAuth = OptionalNullable.of(credentials); } - if (state == 2) { create.basicAuth = OptionalNullable.nullValue(); update.basicAuth = OptionalNullable.nullValue(); } - assertTrue(api.webhooks().create(create).data.hasBasicAuth); - assertTrue(api.webhooks().update("webhook-id", update).data.hasBasicAuth); - for (int i = 0; i < 2; i++) { - RecordedRequest request = server.takeRequest(); - assertEquals(i == 0 ? "POST" : "PUT", request.getMethod()); - assertEquals(i == 0 ? "/v1/webhooks" : "/v1/webhooks/webhook-id", request.getPath()); - assertEquals("Bearer fixture-token", request.getHeader("Authorization")); - assertNull(request.getHeader("x-lettermint-token")); - JsonNode body = mapper.readTree(request.getBody().readUtf8()); - assertEquals(state != 0, body.has("basic_auth")); - if (state == 1) { assertEquals("", body.get("basic_auth").get("password").asText()); assertEquals(" fixture user ", body.get("basic_auth").get("username").asText()); } - if (state == 2) assertTrue(body.get("basic_auth").isNull()); - } - UpdateWebhookData decoded = mapper.readValue(mapper.writeValueAsString(update), UpdateWebhookData.class); - assertEquals(state != 0, decoded.basicAuth != null); - if (state == 1) assertEquals("", decoded.basicAuth.getValue().password); - if (state == 2) assertNull(decoded.basicAuth.getValue()); - } - } - } - - @Test - void allReadModelsExposeOnlyTheSafeFlag() throws Exception { - ObjectMapper mapper = new ObjectMapper(); - assertTrue(mapper.readValue("{\"has_basic_auth\":true}", WebhookData.class).hasBasicAuth); - assertTrue(mapper.readValue("{\"has_basic_auth\":true}", WebhookListData.class).hasBasicAuth); - assertTrue(mapper.readValue("{\"has_basic_auth\":true}", WebhookSecretData.class).hasBasicAuth); - } -} diff --git a/src/test/java/co/lettermint/WebhookTest.java b/src/test/java/co/lettermint/WebhookTest.java index ac0ac0a..6cd886f 100644 --- a/src/test/java/co/lettermint/WebhookTest.java +++ b/src/test/java/co/lettermint/WebhookTest.java @@ -1,222 +1,193 @@ package co.lettermint; -import co.lettermint.exceptions.webhook.InvalidSignatureException; -import co.lettermint.exceptions.webhook.TimestampToleranceException; -import co.lettermint.exceptions.webhook.WebhookVerificationException; -import co.lettermint.webhooks.Webhook; -import org.junit.jupiter.api.Test; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import co.lettermint.exceptions.LettermintConfigException; +import co.lettermint.exceptions.WebhookVerificationException; +import co.lettermint.exceptions.WebhookVerificationException.Reason; +import co.lettermint.types.WebhookEvent; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.time.Clock; +import java.time.Duration; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.ArrayList; +import java.util.Base64; +import java.util.HexFormat; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; - -import static org.junit.jupiter.api.Assertions.*; +import javax.crypto.Mac; +import javax.crypto.spec.SecretKeySpec; +import org.junit.jupiter.api.DynamicTest; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestFactory; class WebhookTest { + private static final String SECRET = "whsec_test0123456789abcdefABCDEF0123"; + private static final long NOW = 1_767_225_600L; + private static final String BODY = "{\"id\":\"dl_1\",\"event\":\"message.delivered\",\"created_at\":\"2026-01-01T00:00:00Z\",\"data\":{\"message_id\":\"m1\"}}"; - private static final String TEST_SECRET = "whsec_test_secret_key"; - - @Test - void testValidSignature() { - String payload = "{\"event\":\"email.sent\",\"data\":{\"messageId\":\"msg_123\"}}"; - long timestamp = System.currentTimeMillis() / 1000; - String hash = computeHmac(timestamp + "." + payload, TEST_SECRET); - String signature = "t=" + timestamp + ",v1=" + hash; - - Map result = Webhook.verify(payload, signature, TEST_SECRET); - - assertEquals("email.sent", result.get("event")); - assertNotNull(result.get("data")); - } - - @Test - void testValidSignatureWithZeroTolerance() { - String payload = "{\"event\":\"test\"}"; - long timestamp = 1000; - String hash = computeHmac(timestamp + "." + payload, TEST_SECRET); - String signature = "t=" + timestamp + ",v1=" + hash; - - Map result = Webhook.verify(payload, signature, TEST_SECRET, 0); - - assertEquals("test", result.get("event")); + private static Clock at(long seconds) { + return Clock.fixed(Instant.ofEpochSecond(seconds), ZoneOffset.UTC); } - @Test - void testInvalidSignature() { - String payload = "{\"event\":\"test\"}"; - long timestamp = System.currentTimeMillis() / 1000; - String signature = "t=" + timestamp + ",v1=invalid_hash"; - - assertThrows(InvalidSignatureException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET)); + private static String sign(String secret, long timestamp, byte[] body) throws Exception { + Mac mac = Mac.getInstance("HmacSHA256"); + mac.init(new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256")); + mac.update((timestamp + ".").getBytes(StandardCharsets.UTF_8)); + return HexFormat.of().formatHex(mac.doFinal(body)); } - @Test - void testTimestampOutsideTolerance() { - String payload = "{\"event\":\"test\"}"; - long oldTimestamp = (System.currentTimeMillis() / 1000) - 600; - String hash = computeHmac(oldTimestamp + "." + payload, TEST_SECRET); - String signature = "t=" + oldTimestamp + ",v1=" + hash; - - TimestampToleranceException ex = assertThrows(TimestampToleranceException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET, 300)); - - assertEquals(oldTimestamp, ex.getTimestamp()); - assertEquals(300, ex.getTolerance()); + private static Map headers(long timestamp, String body) throws Exception { + return Map.of("X-Lettermint-Signature", "t=" + timestamp + ",v1=" + sign(SECRET, timestamp, body.getBytes(StandardCharsets.UTF_8)), + "X-Lettermint-Delivery", String.valueOf(timestamp)); } - @Test - void testFutureTimestampWithinToleranceIsValid() { - String payload = "{\"event\":\"test\"}"; - long futureTimestamp = (System.currentTimeMillis() / 1000) + 5; - String hash = computeHmac(futureTimestamp + "." + payload, TEST_SECRET); - String signature = "t=" + futureTimestamp + ",v1=" + hash; - - Map result = Webhook.verify(payload, signature, TEST_SECRET, 300); - - assertEquals("test", result.get("event")); + private static Reason reason(org.junit.jupiter.api.function.Executable executable) { + return assertThrows(WebhookVerificationException.class, executable).getReason(); } - @Test - void testFutureTimestampOutsideToleranceIsRejected() { - String payload = "{\"event\":\"test\"}"; - long futureTimestamp = (System.currentTimeMillis() / 1000) + 600; - String hash = computeHmac(futureTimestamp + "." + payload, TEST_SECRET); - String signature = "t=" + futureTimestamp + ",v1=" + hash; - - TimestampToleranceException ex = assertThrows(TimestampToleranceException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET, 300)); - - assertEquals(futureTimestamp, ex.getTimestamp()); - assertEquals(300, ex.getTolerance()); - assertTrue(ex.getMessage().contains("future")); - } - - @Test - void testOldTimestampMessageMentionsAge() { - String payload = "{\"event\":\"test\"}"; - long oldTimestamp = (System.currentTimeMillis() / 1000) - 600; - String hash = computeHmac(oldTimestamp + "." + payload, TEST_SECRET); - String signature = "t=" + oldTimestamp + ",v1=" + hash; - - TimestampToleranceException ex = assertThrows(TimestampToleranceException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET, 300)); - - assertTrue(ex.getMessage().contains("too old")); - } + private final Webhook webhook = new Webhook(SECRET, Duration.ofSeconds(300), at(NOW)); @Test - void testCustomTolerance() { - String payload = "{\"event\":\"test\"}"; - long oldTimestamp = (System.currentTimeMillis() / 1000) - 500; - String hash = computeHmac(oldTimestamp + "." + payload, TEST_SECRET); - String signature = "t=" + oldTimestamp + ",v1=" + hash; - - Map result = Webhook.verify(payload, signature, TEST_SECRET, 600); - - assertEquals("test", result.get("event")); - } - - @Test - void testMissingTimestamp() { - String payload = "{\"event\":\"test\"}"; - String signature = "v1=somehash"; - - WebhookVerificationException ex = assertThrows(WebhookVerificationException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET)); - - assertTrue(ex.getMessage().contains("timestamp")); - } - - @Test - void testMissingHash() { - String payload = "{\"event\":\"test\"}"; - String signature = "t=123456"; - - WebhookVerificationException ex = assertThrows(WebhookVerificationException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET)); - - assertTrue(ex.getMessage().contains("hash")); - } - - @Test - void testNullPayload() { - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify(null, "t=123,v1=abc", TEST_SECRET)); - } - - @Test - void testEmptyPayload() { - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify("", "t=123,v1=abc", TEST_SECRET)); - } - - @Test - void testNullSignature() { - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify("{}", null, TEST_SECRET)); - } - - @Test - void testEmptySignature() { - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify("{}", "", TEST_SECRET)); - } - - @Test - void testNullSecret() { - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify("{}", "t=123,v1=abc", null)); - } - - @Test - void testEmptySecret() { - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify("{}", "t=123,v1=abc", "")); + void verifiesAndReturnsThePayload() throws Exception { + WebhookPayload payload = webhook.verify(BODY, headers(NOW - 30, BODY)); + assertEquals("dl_1", payload.id()); + assertEquals(WebhookEvent.MESSAGE_DELIVERED, payload.event()); + assertEquals("2026-01-01T00:00:00Z", payload.timestamp()); + assertEquals(Map.of("message_id", "m1"), payload.data()); + assertEquals("message.delivered", payload.fields().get("event")); + record Delivered(String message_id) { + } + assertEquals(new Delivered("m1"), payload.data(Delivered.class)); + assertEquals("dl_1", webhook.verify(BODY.getBytes(StandardCharsets.UTF_8), headers(NOW, BODY)).id()); + } + + @Test + void acceptsCommonHeaderShapes() throws Exception { + Map single = headers(NOW, BODY); + Map> multi = new LinkedHashMap<>(); + single.forEach((name, value) -> multi.put(name.toLowerCase(), List.of(value))); + webhook.verify(BODY, multi); + Map mixed = new LinkedHashMap<>(); + single.forEach((name, value) -> mixed.put(name.toUpperCase(), new String[] {value})); + webhook.verify(BODY, mixed); + webhook.verify(BODY, name -> single.entrySet().stream().filter(e -> e.getKey().equalsIgnoreCase(name)).map(Map.Entry::getValue).findFirst().orElse(null)); + } + + @Test + void requiresBothHeaders() throws Exception { + Map valid = headers(NOW, BODY); + assertEquals(Reason.SIGNATURE_HEADER_MISSING, reason(() -> webhook.verify(BODY, Map.of("X-Lettermint-Delivery", String.valueOf(NOW))))); + assertEquals(Reason.DELIVERY_HEADER_MISSING, reason(() -> webhook.verify(BODY, Map.of("X-Lettermint-Signature", valid.get("X-Lettermint-Signature"))))); + assertEquals(Reason.DELIVERY_TIMESTAMP_MISMATCH, reason(() -> webhook.verify(BODY, + Map.of("X-Lettermint-Signature", valid.get("X-Lettermint-Signature"), "X-Lettermint-Delivery", String.valueOf(NOW + 1))))); + Map> twice = Map.of("x-lettermint-signature", List.of(valid.get("X-Lettermint-Signature"), valid.get("X-Lettermint-Signature")), + "x-lettermint-delivery", List.of(String.valueOf(NOW))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verify(BODY, twice))); + Map> deliveries = Map.of("x-lettermint-signature", List.of(valid.get("X-Lettermint-Signature")), + "x-lettermint-delivery", List.of(String.valueOf(NOW), String.valueOf(NOW))); + assertEquals(Reason.DELIVERY_TIMESTAMP_MISMATCH, reason(() -> webhook.verify(BODY, deliveries))); + assertEquals(Reason.SIGNATURE_HEADER_MISSING, reason(() -> webhook.verify(BODY, (Map) null))); + } + + @Test + void checksTheToleranceInBothDirections() throws Exception { + webhook.verify(BODY, headers(NOW - 300, BODY)); + webhook.verify(BODY, headers(NOW + 300, BODY)); + assertEquals(Reason.TIMESTAMP_OUT_OF_TOLERANCE, reason(() -> webhook.verify(BODY, headers(NOW - 301, BODY)))); + assertEquals(Reason.TIMESTAMP_OUT_OF_TOLERANCE, reason(() -> webhook.verify(BODY, headers(NOW + 301, BODY)))); + Webhook strict = new Webhook(SECRET, Duration.ZERO, at(NOW)); + strict.verify(BODY, headers(NOW, BODY)); + assertEquals(Reason.TIMESTAMP_OUT_OF_TOLERANCE, reason(() -> strict.verify(BODY, headers(NOW - 1, BODY)))); + } + + @Test + void rejectsTamperingAndMalformedHeaders() throws Exception { + String signature = sign(SECRET, NOW, BODY.getBytes(StandardCharsets.UTF_8)); + String other = sign("whsec_other", NOW, BODY.getBytes(StandardCharsets.UTF_8)); + assertEquals(Reason.SIGNATURE_MISMATCH, reason(() -> webhook.verifySignature(BODY.replace("m1", "m2"), "t=" + NOW + ",v1=" + signature))); + webhook.verifySignature(BODY, "t=" + NOW + ",v1=" + other + ",v1=" + signature); + webhook.verifySignature(BODY, "t=" + NOW + ",v1=" + signature + ",v1=" + other); + webhook.verifySignature(BODY, "t=" + NOW + ",v0=abc,v1=" + signature, String.valueOf(NOW)); + assertEquals(Reason.SIGNATURE_MISMATCH, reason(() -> new Webhook("test0123456789abcdefABCDEF0123", Duration.ofSeconds(300), at(NOW)) + .verifySignature(BODY, "t=" + NOW + ",v1=" + signature))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "t=" + NOW + ",t=" + NOW + ",v1=" + signature))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "v1=" + signature))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "t=" + NOW))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "t=abc,v1=" + signature))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "t=99999999999999999999,v1=" + signature))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "t=" + NOW + ",v1=é" + signature.substring(1)))); + assertEquals(Reason.SIGNATURE_HEADER_MALFORMED, reason(() -> webhook.verifySignature(BODY, "t=1767225600,v1=" + signature))); + assertEquals(Reason.SIGNATURE_HEADER_MISSING, reason(() -> webhook.verifySignature(BODY, " "))); + assertEquals(Reason.BODY_INVALID, reason(() -> webhook.verifySignature("", "t=" + NOW + ",v1=" + signature))); + assertEquals(Reason.BODY_INVALID, reason(() -> webhook.verifySignature((byte[]) null, "t=" + NOW + ",v1=" + signature))); + } + + @Test + void rejectsPayloadsThatAreNotJsonObjects() throws Exception { + for (String body : new String[] {"[1]", "not json", "\"text\""}) { + String header = "t=" + NOW + ",v1=" + sign(SECRET, NOW, body.getBytes(StandardCharsets.UTF_8)); + assertEquals(Reason.PAYLOAD_INVALID, reason(() -> webhook.verifySignature(body, header))); + } } @Test - void testInvalidJsonPayload() { - String payload = "not valid json"; - long timestamp = System.currentTimeMillis() / 1000; - String hash = computeHmac(timestamp + "." + payload, TEST_SECRET); - String signature = "t=" + timestamp + ",v1=" + hash; - - assertThrows(WebhookVerificationException.class, - () -> Webhook.verify(payload, signature, TEST_SECRET)); + void validatesItsConfiguration() { + assertThrows(LettermintConfigException.class, () -> new Webhook("")); + assertThrows(LettermintConfigException.class, () -> new Webhook(null)); + assertThrows(LettermintConfigException.class, () -> new Webhook(SECRET, Duration.ofSeconds(-1))); + assertThrows(LettermintConfigException.class, () -> new Webhook(SECRET, Duration.ofMillis(1500))); + assertEquals(Duration.ofSeconds(300), new Webhook(SECRET).tolerance()); } @Test - void testSignatureWithExtraWhitespace() { - String payload = "{\"event\":\"test\"}"; - long timestamp = System.currentTimeMillis() / 1000; - String hash = computeHmac(timestamp + "." + payload, TEST_SECRET); - String signature = "t = " + timestamp + ", v1 = " + hash; - - Map result = Webhook.verify(payload, signature, TEST_SECRET); - - assertEquals("test", result.get("event")); + void neverPrintsTheSecret() { + String text = webhook.toString(); + assertEquals("Webhook{tolerance=300s}", text); + WebhookVerificationException error = assertThrows(WebhookVerificationException.class, + () -> webhook.verify("{}", Map.of("X-Lettermint-Signature", "t=1,v1=" + "0".repeat(64), "X-Lettermint-Delivery", "1"))); + assertFalse(error.toString().contains(SECRET)); + assertFalse(error.getMessage().contains(SECRET)); + assertEquals("timestamp_out_of_tolerance", error.getReason().code()); } - private String computeHmac(String data, String secret) { - try { - Mac mac = Mac.getInstance("HmacSHA256"); - SecretKeySpec secretKeySpec = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); - mac.init(secretKeySpec); - byte[] hmacBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); - - StringBuilder hexString = new StringBuilder(); - for (byte b : hmacBytes) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) { - hexString.append('0'); + @TestFactory + List sharedVectors() throws Exception { + JsonNode vectors; + try (InputStream in = getClass().getResourceAsStream("/webhooks.json")) { + vectors = new ObjectMapper().readTree(in); + } + List tests = new ArrayList<>(); + for (JsonNode vector : vectors.get("vectors")) { + tests.add(DynamicTest.dynamicTest(vector.get("id").asText(), () -> { + Webhook verifier = new Webhook(vector.get("secret").asText(), Duration.ofSeconds(vector.get("tolerance").asLong()), at(vector.get("now").asLong())); + Map headers = new LinkedHashMap<>(); + vector.get("headers").properties().forEach(entry -> headers.put(entry.getKey(), entry.getValue().asText())); + byte[] body = Base64.getDecoder().decode(vector.get("body_base64").asText()); + String expect = vector.get("expect").asText(); + try { + verifier.verify(body, headers); + if (!expect.equals("valid")) { + fail("expected " + vector.get("reason").asText()); + } + } catch (WebhookVerificationException error) { + if (expect.equals("valid")) { + fail("expected valid, got " + error.getReason().code() + ": " + error.getMessage()); + } + assertEquals(vector.get("reason").asText(), error.getReason().code()); } - hexString.append(hex); - } - return hexString.toString(); - } catch (Exception e) { - throw new RuntimeException(e); + })); } + assertTrue(tests.size() >= 25); + return tests; } } diff --git a/src/test/resources/webhooks.json b/src/test/resources/webhooks.json new file mode 100644 index 0000000..caa3fd9 --- /dev/null +++ b/src/test/resources/webhooks.json @@ -0,0 +1,444 @@ +{ + "description": "Lettermint webhook verification vectors. Generated by conformance/tools/make_webhook_vectors.py; do not edit.", + "scheme": { + "signature_header": "X-Lettermint-Signature: t=,v1=.' + raw body)>", + "delivery_header": "X-Lettermint-Delivery: , equal to t. Required.", + "secret": "Used as-is, including the whsec_ prefix.", + "tolerance": "Accept when |now - t| <= tolerance, in both directions.", + "multiple_v1": "Accept when any v1 matches." + }, + "reasons": [ + "valid", + "signature_header_missing", + "signature_header_malformed", + "timestamp_out_of_tolerance", + "delivery_header_missing", + "delivery_timestamp_mismatch", + "signature_mismatch" + ], + "vectors": [ + { + "id": "valid-basic", + "description": "A delivery exactly as the backend sends it.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-lowercase-header-names", + "description": "Header names arrive lower-cased, as Node.js and most frameworks expose them.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "x-lettermint-signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "x-lettermint-delivery": "1767225570", + "x-lettermint-event": "message.delivered", + "x-lettermint-attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-raw-bytes-non-ascii-utf8", + "description": "The body contains multi-byte UTF-8. Verify the raw bytes, not a re-encoded string.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=d86abc23d77d6cc64037a2c7bf81bfc97f4c54f3332e5dcb6deeefc4a770631c", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6Ikdyw7zDn2UgYXVzIFrDvHJpY2gg4oCTIOadseS6rCDwn5qAIiwicmVjaXBpZW50IjoicmVjaXBpZW50QGV4YW1wbGUuY29tIiwidXJsIjoiaHR0cHM6Ly9leGFtcGxlLmNvbS9hL2I/Yz1kIn0sImNvbnRleHQiOnsicHJvamVjdF9pZCI6IjAxOTliMGU2LTAwMDAtNzAwMC04MDAwLTAwMDAwMDAwMDBhYSJ9fQ==", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Grüße aus Zürich – 東京 🚀\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-key-rotation-second-v1-matches", + "description": "Two v1 values; only the second matches. Any matching v1 is accepted.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=78d40acbde7a1d62e558ccb262f80452400d3121afbd391dbc4a9d3d977781f0,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-key-rotation-first-v1-matches", + "description": "Two v1 values; only the first matches. A verifier that checks only the last v1 fails this.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62,v1=78d40acbde7a1d62e558ccb262f80452400d3121afbd391dbc4a9d3d977781f0", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-unknown-scheme-ignored", + "description": "An unknown scheme next to a matching v1 is ignored.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62,v2=abababababababababababababababababababababababababababababababab", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-timestamp-past-within-tolerance", + "description": "Signed 120 seconds before now.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225480,v1=d9d5742f8e6ed427651981a955b4898953b06251d4d54d95822f82c31feef2f5", + "X-Lettermint-Delivery": "1767225480", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-timestamp-future-within-tolerance", + "description": "Signed 120 seconds after now (receiver clock behind).", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225720,v1=d2031a10b1b71d08b0557f4cfda07dc06489df741689661b7cb291a8cf7bc4bd", + "X-Lettermint-Delivery": "1767225720", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-timestamp-past-at-boundary", + "description": "Signed exactly `tolerance` seconds before now; the boundary is accepted.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225300,v1=29436298f2468c1fcc397ff6f23553eac2dce5a71d5c1195d2fe5adca7d5a261", + "X-Lettermint-Delivery": "1767225300", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "valid-timestamp-future-at-boundary", + "description": "Signed exactly `tolerance` seconds after now; the boundary is accepted.", + "expect": "valid", + "reason": "valid", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225900,v1=d6f11c156c62816ecd4cc5d39e793b35389253ecf103b9a76b698cd2f922b115", + "X-Lettermint-Delivery": "1767225900", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-timestamp-past-beyond-tolerance", + "description": "Signed tolerance + 1 seconds before now (replay).", + "expect": "invalid", + "reason": "timestamp_out_of_tolerance", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225299,v1=a8a0c4956ac712924ca805ceed443718b0c38e98a2bbe1c85ed9e31e1d26b26d", + "X-Lettermint-Delivery": "1767225299", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-timestamp-future-beyond-tolerance", + "description": "Signed tolerance + 1 seconds after now.", + "expect": "invalid", + "reason": "timestamp_out_of_tolerance", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225901,v1=23ab3a289112633d24dbd423b2eb5d523608057130cebb6e07abbeb98767a2b2", + "X-Lettermint-Delivery": "1767225901", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-body-tampered", + "description": "One character of the body changed after signing.", + "expect": "invalid", + "reason": "signature_mismatch", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybXludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermynt\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-body-reserialized", + "description": "The body was re-serialised with escaped slashes; the signature covers the original bytes.", + "expect": "invalid", + "reason": "signature_mismatch", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOlwvXC9leGFtcGxlLmNvbVwvYVwvYj9jPWQifSwiY29udGV4dCI6eyJwcm9qZWN0X2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMGFhIn19", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https:\\/\\/example.com\\/a\\/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-wrong-secret", + "description": "Signed with a different secret.", + "expect": "invalid", + "reason": "signature_mismatch", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=ed59387c3cd9af2e957f07606ed6416da05fd1cf35696dda47586292fe090546", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-secret-prefix-stripped", + "description": "Signed with the secret minus its whsec_ prefix. The secret is used as-is.", + "expect": "invalid", + "reason": "signature_mismatch", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=a29a6b254dcc0ba4662871e6c088380185375e1b552a94d36339f678baa59ed7", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-key-rotation-no-v1-matches", + "description": "Two v1 values and neither matches.", + "expect": "invalid", + "reason": "signature_mismatch", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=78d40acbde7a1d62e558ccb262f80452400d3121afbd391dbc4a9d3d977781f0,v1=0000000000000000000000000000000000000000000000000000000000000000", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-signature-header-missing", + "description": "X-Lettermint-Signature is absent.", + "expect": "invalid", + "reason": "signature_header_missing", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-signature-missing-timestamp", + "description": "The signature header has v1 but no t.", + "expect": "invalid", + "reason": "signature_header_malformed", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-signature-missing-v1", + "description": "The signature header has t but no v1.", + "expect": "invalid", + "reason": "signature_header_malformed", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-signature-timestamp-not-numeric", + "description": "t is not a number.", + "expect": "invalid", + "reason": "signature_header_malformed", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=abc,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-signature-non-ascii-in-v1", + "description": "The v1 value ends in a non-ASCII character. Reject it; do not crash.", + "expect": "invalid", + "reason": "signature_header_malformed", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec6é", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-signature-non-ascii-timestamp-digits", + "description": "t uses full-width Unicode digits; v1 is valid for the ASCII timestamp. Parsers that accept Unicode digits wrongly accept it.", + "expect": "invalid", + "reason": "signature_header_malformed", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225570", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-delivery-header-missing", + "description": "X-Lettermint-Delivery is absent. The backend always sends it (WebhookService.php:102), so it is required.", + "expect": "invalid", + "reason": "delivery_header_missing", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + }, + { + "id": "invalid-delivery-header-mismatch", + "description": "X-Lettermint-Delivery differs from t. The backend always sends them equal.", + "expect": "invalid", + "reason": "delivery_timestamp_mismatch", + "secret": "whsec_conformance0123456789abcdefABCDEF01", + "now": 1767225600, + "tolerance": 300, + "headers": { + "X-Lettermint-Signature": "t=1767225570,v1=14b942853f50d3d313f71135ee85933b89fbd0302b93faefff4be84c61a2ec62", + "X-Lettermint-Delivery": "1767225571", + "X-Lettermint-Event": "message.delivered", + "X-Lettermint-Attempt": "1" + }, + "body_base64": "eyJpZCI6IjAxOTk5YjBlLTZjMWQtN2E4Yi05YzBkLTFlMmYzYTRiNWM2ZCIsImV2ZW50IjoibWVzc2FnZS5kZWxpdmVyZWQiLCJjcmVhdGVkX2F0IjoiMjAyNS0xMi0zMVQyMzo1OTozMC4wMDAwMDBaIiwiZGF0YSI6eyJtZXNzYWdlX2lkIjoiMDE5OWIwZTYtMDAwMC03MDAwLTgwMDAtMDAwMDAwMDAwMDAxIiwic3ViamVjdCI6IldlbGNvbWUgdG8gTGV0dGVybWludCIsInJlY2lwaWVudCI6InJlY2lwaWVudEBleGFtcGxlLmNvbSIsInVybCI6Imh0dHBzOi8vZXhhbXBsZS5jb20vYS9iP2M9ZCJ9LCJjb250ZXh0Ijp7InByb2plY3RfaWQiOiIwMTk5YjBlNi0wMDAwLTcwMDAtODAwMC0wMDAwMDAwMDAwYWEifX0=", + "body_utf8": "{\"id\":\"01999b0e-6c1d-7a8b-9c0d-1e2f3a4b5c6d\",\"event\":\"message.delivered\",\"created_at\":\"2025-12-31T23:59:30.000000Z\",\"data\":{\"message_id\":\"0199b0e6-0000-7000-8000-000000000001\",\"subject\":\"Welcome to Lettermint\",\"recipient\":\"recipient@example.com\",\"url\":\"https://example.com/a/b?c=d\"},\"context\":{\"project_id\":\"0199b0e6-0000-7000-8000-0000000000aa\"}}" + } + ] +} From 53973618af319c61cc6f9d91cf399170e21b5b11 Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Sat, 3 Oct 2026 23:59:44 +0200 Subject: [PATCH 4/6] ci: test Java 17, 21 and 25 and release the version from the tag The release workflow passes -PreleaseVersion instead of editing build.gradle and the removed pom.xml, and checks the jar manifest and BuildInfo before publishing. CI runs ./gradlew build, which includes javadoc and the generated-header check. --- .github/workflows/ci.yml | 17 ++++++++--------- .github/workflows/release.yml | 16 +++++++++++----- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d562474..2865e5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,8 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest, windows-latest] - java: [8, 11, 17, 21] + # 17 is the minimum; 21 and 25 are the current LTS releases. + java: [17, 21, 25] steps: - name: Checkout code @@ -34,12 +35,11 @@ jobs: run: chmod +x gradlew if: runner.os != 'Windows' - - name: Build with Gradle + # build runs the tests, javadoc and checkGeneratedTypes. The SDK generator is + # private, so CI only verifies the headers of src/main/java/co/lettermint/types. + - name: Build and test run: ./gradlew build --no-daemon - - name: Run tests - run: ./gradlew test --no-daemon - - name: Upload test results uses: actions/upload-artifact@v7 if: failure() @@ -71,7 +71,6 @@ jobs: - name: Check build output run: | - if [ ! -d "build/libs" ]; then - echo "Build output directory 'build/libs' not found" - exit 1 - fi + jar=$(ls build/libs/lettermint-*.jar | grep -v -e sources -e javadoc) + unzip -p "$jar" META-INF/MANIFEST.MF | grep -q 'Automatic-Module-Name: co.lettermint' + if unzip -l "$jar" | grep -q okhttp; then echo "okhttp must not be bundled"; exit 1; fi diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d822fb7..a44fe95 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [8, 11, 17, 21] + java: [17, 21, 25] steps: - name: Checkout code @@ -36,7 +36,7 @@ jobs: run: chmod +x gradlew - name: Run tests - run: ./gradlew test --no-daemon + run: ./gradlew build --no-daemon release: name: Release @@ -71,8 +71,14 @@ jobs: fi echo "RELEASE_VERSION=$version" >> "$GITHUB_ENV" - perl -0pi -e "s/^version = '.*'$/version = '$version'/m" build.gradle - RELEASE_VERSION="$version" perl -0pi -e 's|(lettermint\s*)[^<]+()|$1$ENV{RELEASE_VERSION}$2|' pom.xml + + # build.gradle reads the version from -PreleaseVersion; check the jar before publishing. + - name: Build and check the release version + run: | + ./gradlew build -PreleaseVersion="$RELEASE_VERSION" --no-daemon + jar="build/libs/lettermint-$RELEASE_VERSION.jar" + unzip -p "$jar" META-INF/MANIFEST.MF | grep -q "Implementation-Version: $RELEASE_VERSION" + unzip -p "$jar" co/lettermint/BuildInfo.class | grep -q "$RELEASE_VERSION" - name: Publish to Maven Central env: @@ -83,7 +89,7 @@ jobs: GPG_PRIVATE_KEY_BASE64: ${{ secrets.GPG_PRIVATE_KEY }} run: | export ORG_GRADLE_PROJECT_signingKey=$(echo "$GPG_PRIVATE_KEY_BASE64" | base64 -d) - ./gradlew publish --no-daemon + ./gradlew publish -PreleaseVersion="$RELEASE_VERSION" --no-daemon - name: Release staging repository env: From 1728c7f6c197a03828a37e7d03fb68ccea81691c Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Sun, 4 Oct 2026 00:08:09 +0200 Subject: [PATCH 5/6] docs: rewrite the README for 3.0 and add the 2.x upgrade guide UPGRADE.md has before/after examples for every changed call, the full type rename table, the removed classes and types, and a ready-to-copy instruction for upgrading with a coding agent. --- README.md | 465 ++++++++++++++++++++++++++++++++++------------------ UPGRADE.md | 472 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 773 insertions(+), 164 deletions(-) diff --git a/README.md b/README.md index 94d53f1..8c353bd 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,9 @@ ![Build Status](https://img.shields.io/github/actions/workflow/status/lettermint/lettermint-java/release.yml?branch=main) [![Join our Discord server](https://img.shields.io/discord/1305510095588819035?logo=discord&logoColor=eee&label=Discord&labelColor=464ce5&color=0D0E28&cacheSeconds=43200)](https://lettermint.co/r/discord) -The official Java SDK for [Lettermint](https://lettermint.co). +The official Java SDK for [Lettermint](https://lettermint.co). It runs on Java 17 or later, uses the JDK's `java.net.http` client and depends only on Jackson. -## Requirements - -- Java 8 or higher +Upgrading from 2.x? Read [UPGRADE.md](UPGRADE.md). ## Installation @@ -18,269 +16,410 @@ The official Java SDK for [Lettermint](https://lettermint.co). co.lettermint lettermint - 2.0.0 + 3.0.0 ``` ### Gradle ```groovy -implementation 'co.lettermint:lettermint:2.0.0' +implementation 'co.lettermint:lettermint:3.0.0' ``` -## Quick Start +## Quick start + +Create a client with a project sending token and send an email: ```java +import co.lettermint.EmailMessage; import co.lettermint.Lettermint; -import co.lettermint.endpoints.EmailEndpoint; -import co.lettermint.models.SendEmailResponse; +import co.lettermint.types.SendMailResponse; -EmailEndpoint email = Lettermint.email("your-sending-token"); +Lettermint lettermint = Lettermint.builder() + .sendingToken(System.getenv("LETTERMINT_PROJECT_TOKEN")) + .build(); -SendEmailResponse response = email - .from("sender@example.com") - .to("recipient@example.com") - .subject("Hello from Lettermint") - .html("

Hello World!

") - .send(); +SendMailResponse result = lettermint.emails().send(EmailMessage.create() + .from("Acme ") + .to("jane@example.com") + .subject("Welcome to Acme") + .html("

Thanks for signing up.

") + .text("Thanks for signing up.")); -System.out.println("Message ID: " + response.getMessageId()); +System.out.println(result.messageId() + " " + result.status()); // "…", "pending" ``` -## Usage +The client is immutable and thread-safe and holds no message state. Create it once (for example as a Spring bean) and share it. + +## Tokens -### Sending Emails +Lettermint has two kinds of API tokens: -Use a project sending token with `Lettermint.email(...)`. Sending tokens authenticate with the `x-lettermint-token` header. +| Builder method | Token | Used by | Sent as | +| --- | --- | --- | --- | +| `sendingToken(...)` | Project sending token (`lm_…`) | `lettermint.emails()` | `x-lettermint-token` header | +| `teamToken(...)` | Team API token (`lm_team_…`) | Every other part (domains, messages, projects, …) | `Authorization: Bearer` header | -The SDK provides a fluent builder interface for composing emails: +Pass one or both: ```java -import co.lettermint.Lettermint; -import co.lettermint.endpoints.EmailEndpoint; -import co.lettermint.models.SendEmailResponse; +Lettermint lettermint = Lettermint.builder() + .sendingToken(System.getenv("LETTERMINT_PROJECT_TOKEN")) + .teamToken(System.getenv("LETTERMINT_TEAM_TOKEN")) + .build(); +``` -import java.util.HashMap; -import java.util.Map; +Each part uses its own token and never falls back to the other one. If the token a method needs is missing, it throws a `LettermintConfigException` that names it (`domains.list needs teamToken; …`), before any request. `lettermint.ping()` uses the team token when it is set, otherwise the sending token. `messages().reschedule()` and `messages().cancel()` accept either token in the same way. -EmailEndpoint email = Lettermint.email("your-sending-token"); +You can also pass a single token and let the SDK choose its type by the format: `lm_team_` followed by letters and digits is a team token, and `lm_` followed by letters and digits is a sending token. -Map headers = new HashMap<>(); -headers.put("X-Custom-Header", "value"); +```java +Lettermint lettermint = Lettermint.of(System.getenv("LETTERMINT_TOKEN")); +// With other options: +Lettermint lettermint = Lettermint.builder().token(System.getenv("LETTERMINT_TOKEN")).timeout(Duration.ofSeconds(10)).build(); +``` -Map metadata = new HashMap<>(); -metadata.put("userId", "123"); -metadata.put("campaign", "welcome"); +Any other format, such as an SSO verification token (`lm_sso_…`), throws `LettermintConfigException`; use `sendingToken(...)` or `teamToken(...)` for those. Error messages never contain the token. -SendEmailResponse response = email - // Sender - .from("John Doe ") +### Options - // Recipients (varargs) - .to("recipient1@example.com", "recipient2@example.com") - .cc("cc@example.com") - .bcc("bcc@example.com") - .replyTo("reply@example.com") +| Builder method | Default | Description | +| --- | --- | --- | +| `sendingToken(String)` | | Project sending token. | +| `teamToken(String)` | | Team API token. | +| `token(String)` | | Either token, detected by its format. | +| `baseUrl(String)` | `https://api.lettermint.co/v1` | API base URL. | +| `timeout(Duration)` | 30 seconds | Request timeout. It covers the whole request: connecting, sending, the response headers and the body. | +| `httpClient(HttpClient)` | a new `java.net.http.HttpClient` | Your own client, for example with a proxy, TLS settings or an executor. It must not follow redirects (`HttpClient.Redirect.NEVER`, the JDK default). | - // Content - .subject("Welcome!") - .html("

Hello World

") - .text("Hello World") +## Sending email - // Custom headers - .headers(headers) - // Or add headers individually - .header("X-Another-Header", "value") +### Messages - // Attachments - .attach("document.pdf", base64EncodedContent) - .attach("logo.png", base64EncodedContent, "logo") // Inline with content ID +`EmailMessage` is immutable: every setter returns a new message and leaves the original unchanged. Each setter has an accessor of the same name (`message.subject()`). - // Routing - .route("route-id") +```java +EmailMessage message = EmailMessage.create() + .from("Acme ") + .to("jane@example.com") + .replyTo("support@acme.com") + .subject("Your order has shipped") + .html(html) + .metadata(Map.of("order_id", "1234")); + +lettermint.emails().send(message); +``` - // Metadata and tags - .metadata(metadata) - .tag("legacy-tag") - .tags( - new MessageTag("campaign", "welcome"), - new MessageTag("customer", "new") - ) +### The email builder - // Idempotency - .idempotencyKey("unique-request-key") +`emails().compose()` returns an immutable builder bound to the client, with the same setters plus `send()`. Every setter returns a new builder, so you can keep a base builder and reuse it, also across threads: - .send(); -``` +```java +EmailBuilder welcome = lettermint.emails().compose() + .from("Acme ") + .subject("Welcome to Acme") + .tags(new MessageTagInput("campaign", "welcome")); -`tag()` remains available for the legacy single tag. The previous map form of -`tags()` also remains available. +welcome.to("jane@example.com").html("

Hi Jane

").send(); +welcome.to("john@example.com").html("

Hi John

").send(); +``` -Existing constructor-based sending usage still works: +When you build an email over several statements, keep the returned builder: ```java -Lettermint lettermint = new Lettermint("your-sending-token"); -lettermint.email().from("sender@example.com").to("recipient@example.com").subject("Hello").send(); +EmailBuilder email = lettermint.emails().compose().from("hello@acme.com").to(user.email()).subject("Your invoice"); +if (user.accountant() != null) { + email = email.cc(user.accountant()); +} +email.html(invoiceHtml).send(); ``` -### Batch Sending +| Method | Description | +| --- | --- | +| `from(address)` | Sender, for example `Acme `. | +| `to(...)`, `cc(...)`, `bcc(...)`, `replyTo(...)` | Replace the recipient list (varargs or a collection). | +| `subject(text)` | Subject line. | +| `html(html)`, `text(text)` | Bodies. `null` removes one. | +| `headers(map)` | Custom email headers. | +| `metadata(map)` | Data stored with the message, not added as headers. | +| `tags(MessageTagInput...)`, `tag(name)` | Name/value tags, and the legacy single tag. | +| `route(slug)` | The route to send through. | +| `scheduledAt(String or Instant)` | Delivery time: an `Instant`, ISO 8601, or English such as `tomorrow 9am`. | +| `settings(SendMailRequestSettings)` | Per-email settings that override the route. | +| `sandboxResult(SandboxResult)` | The result a Sandbox project simulates. | +| `attach(EmailAttachment)` | Adds an attachment. | +| `send()`, `send(SendOptions)` | Sends the email. The builder can be sent again. | +| `build()` | Returns the `EmailMessage`. | + +`emails().compose(message)` starts a builder from a message. `message.toRequest()` returns the API's wire format (`SendMailRequest`). + +### Batch sending + +Send up to 500 emails in one request: ```java -import co.lettermint.models.api.SendMailRequest; -import co.lettermint.models.api.SendMailResponse; +List results = lettermint.emails().sendBatch(List.of( + EmailMessage.create().from("hello@acme.com").to("jane@example.com").subject("Hi Jane").text("Hello"), + welcome.to("john@example.com").html("

Hi John

").build())); +``` -import java.util.Collections; -import java.util.List; +### Idempotency -SendMailRequest message = new SendMailRequest(); -message.fromValue = "sender@example.com"; -message.to = Collections.singletonList("recipient@example.com"); -message.subject = "Hello from Lettermint"; -message.text = "This is a batch email."; +Pass an idempotency key to make retries safe. The API processes a key once, so a retry with the same key does not send the email again. The key applies only to the call it is passed to. -List response = Lettermint.email("your-sending-token") - .sendBatch(Collections.singletonList(message)); +```java +lettermint.emails().send(message, SendOptions.idempotencyKey("order-" + order.id() + "-confirmation")); +builder.send(SendOptions.idempotencyKey("welcome-jane")); +lettermint.emails().sendBatch(messages, SendOptions.idempotencyKey("newsletter-2026-10")); ``` -Both sending and API clients support `ping()`: +The SDK never retries on its own. + +### Scheduling ```java -String pong = Lettermint.email("your-sending-token").ping(); +SendMailResponse result = lettermint.emails().compose() + .from("hello@acme.com") + .to("jane@example.com") + .subject("Your trial ends tomorrow") + .text("…") + .scheduledAt(Instant.now().plus(Duration.ofDays(1))) + .send(); + +if (MessageStatus.SCHEDULED.equals(result.status())) { + System.out.println(result.scheduledAt()); +} + +lettermint.messages().reschedule(result.messageId(), new RescheduleMessageRequest("2026-10-20T09:00:00Z")); +lettermint.messages().cancel(result.messageId()); ``` -### Team API +### Sandbox -Use a team API token with `Lettermint.api(...)`. API tokens authenticate with `Authorization: Bearer ...` and are separate from project sending tokens. +In a Sandbox project, nothing is delivered. Choose the simulated result per email: ```java -import co.lettermint.Lettermint; -import co.lettermint.api.ApiClient; -import co.lettermint.models.api.DomainIndexResponse; -import co.lettermint.models.api.TeamData; +SendMailResponse result = lettermint.emails().compose() + .from("hello@acme.com") + .to("jane@example.com") + .subject("Test") + .text("Test") + .sandboxResult(SandboxResult.HARD_BOUNCED) + .send(); + +System.out.println(result.sandbox() + " " + result.sandboxResult()); // true hard_bounced +``` -import java.util.Collections; -import java.util.Map; +### Tags -ApiClient api = Lettermint.api("your-api-token"); +`tags(...)` accepts up to 20 case-sensitive name/value tags (19 when the legacy `tag(...)` is also set). Names match `^[A-Za-z0-9_-]{1,32}$`, may not start with `__lettermint` and must be unique. Values match `^[A-Za-z0-9_-]{1,64}$`. The SDK checks this before the request and throws `LettermintValidationException`. Because messages and builders are immutable, a rejected tag leaves them unchanged. -Map query = Collections.singletonMap("page[size]", "10"); +### Attachments -DomainIndexResponse domains = api.domains().list(query); -TeamData team = api.team().retrieve(); -String messageHtml = api.messages().html("message-id"); -String pong = api.ping(); +```java +lettermint.emails().compose() + .from("billing@acme.com") + .to("jane@example.com") + .subject("Your invoice") + .html(" Your invoice is attached.") + .attach(EmailAttachment.of("invoice.pdf", Files.readAllBytes(invoicePath)).contentType("application/pdf")) + .attach(EmailAttachment.ofBase64("logo.png", logoBase64).contentId("logo")) + .send(); ``` -Endpoint groups are available as `domains()`, `messages()`, `projects()`, `routes()`, `stats()`, `suppressions()`, `team()`, and `webhooks()`. +`EmailAttachment.of` takes raw bytes, which the SDK base64-encodes; `ofBase64` takes content that is already encoded. `lettermint.blockedFileTypes()` lists the extensions and MIME types the API rejects. -### Webhook Verification +## Team API -Verify webhook signatures to ensure requests are from Lettermint: +With a team token, the client manages domains, messages, projects, routes, statistics, suppressions, the team and webhooks: ```java -import co.lettermint.webhooks.Webhook; -import co.lettermint.exceptions.webhook.WebhookVerificationException; +Lettermint lettermint = Lettermint.builder().teamToken(System.getenv("LETTERMINT_TEAM_TOKEN")).build(); -import java.util.Map; +DomainData domain = lettermint.domains().create(new StoreDomainData("acme.com")); +lettermint.domains().verifyDnsRecords(domain.id()); -String rawPayload = "..."; // Raw JSON body from request -String signature = "..."; // Value of X-Lettermint-Signature header -String secret = "whsec_..."; // Your webhook signing secret +ProjectCreatedData project = lettermint.projects().create(StoreProjectData.builder().name("Production").build()); +System.out.println(project.apiToken()); // the new project's sending token, shown once -try { - Map payload = Webhook.verify(rawPayload, signature, secret); +StatsData stats = lettermint.stats().retrieve(GetStatsQuery.builder().from("2026-10-01").to("2026-10-31").build()); +String html = lettermint.messages().html("message-id"); +``` - String event = (String) payload.get("event"); - Map data = (Map) payload.get("data"); +| Accessor | Methods | +| --- | --- | +| `domains()` | `list`, `iterate`, `create`, `retrieve`, `delete`, `verifyDnsRecords`, `verifyDnsRecord`, `updateProjects` | +| `messages()` | `list`, `iterate`, `retrieve`, `events`, `iterateEvents`, `source`, `html`, `text`, `reschedule`, `cancel`, `process` | +| `projects()` | `list`, `iterate`, `create`, `retrieve`, `update`, `delete`, `rotateToken` | +| `projects().reportForwarding()` | `retrieve`, `update`, `delete`, `verify`, `resendCode` | +| `routes()` | `list(projectId)`, `iterate(projectId)`, `create(projectId, …)`, `retrieve`, `update`, `delete`, `verifyInboundDomain` | +| `stats()` | `retrieve` | +| `suppressions()` | `list`, `iterate`, `create`, `delete` | +| `team()` | `retrieve`, `update`, `usage`, `roles` | +| `team().members()` | `list`, `iterate`, `retrieve`, `updateAssignment` | +| `webhooks()` | `list`, `iterate`, `create`, `retrieve`, `update`, `delete`, `test`, `regenerateSecret` | +| `webhooks().deliveries()` | `list(webhookId)`, `iterate(webhookId)`, `retrieve(webhookId, deliveryId)` | +| (root) | `ping`, `analytics`, `blockedFileTypes` | + +Request and response types are immutable records in `co.lettermint.types`. Build requests with their builder (`UpdateRouteData.builder().name("Main").build()`) or, for small ones, the constructor (`new StoreDomainData("acme.com")`). In update requests, a field that is optional and nullable is an `OptionalNullable`: leave it unset to keep the current value, or pass `null` to the builder to clear it: - // Handle the webhook event -} catch (WebhookVerificationException e) { - // Invalid signature -} +```java +lettermint.routes().update(routeId, UpdateRouteData.builder().inboundDomain(null).build()); // {"inbound_domain": null} ``` -With custom timestamp tolerance (in seconds): +### Query parameters and pagination + +Query parameters are typed records with builders. The SDK sends them in the API's bracket syntax (`page[size]=30&filter[status]=verified&sort=-created_at`): ```java -// Allow signatures up to 10 minutes old -Map payload = Webhook.verify(rawPayload, signature, secret, 600); +CursorPage page = lettermint.domains().list(ListDomainsQuery.builder() + .pageSize(30) + .filterStatus(DomainStatus.VERIFIED) + .sort(List.of(ListDomainsQuerySortItem.CREATED_AT_DESC)) + .build()); -// Disable timestamp checking -Map payload = Webhook.verify(rawPayload, signature, secret, 0); +System.out.println(page.data().size() + " " + page.nextCursor()); ``` -## Exception Handling +Every list has an `iterate()` method that follows `nextCursor` until the last page. It returns a `CursorIterable`, which you can loop over or stream; pages are requested only when you get to them: -The SDK uses unchecked exceptions that extend `RuntimeException`: +```java +for (MessageListData message : lettermint.messages().iterate(ListMessagesQuery.builder().filterStatus(MessageStatus.HARD_BOUNCED).build())) { + System.out.println(message.id() + " " + message.subject()); +} + +lettermint.webhooks().deliveries().iterate(webhookId).stream().limit(100).forEach(System.out::println); +``` + +### Timeouts and cancellation + +Every method takes an optional last argument with per-call options: `RequestOptions.timeout(Duration)`, or `SendOptions` for calls that also take an idempotency key. ```java -import co.lettermint.exceptions.*; +lettermint.messages().list(null, RequestOptions.timeout(Duration.ofSeconds(5))); +``` + +To cancel a call, interrupt the calling thread. The SDK aborts the request and throws `java.util.concurrent.CancellationException` with the thread's interrupt status set. + +The SDK is synchronous. On Java 21, virtual threads make blocking calls cheap; to run a call asynchronously, use `CompletableFuture.supplyAsync(() -> lettermint.emails().send(message), executor)`. + +## Errors + +Every exception the SDK throws is unchecked and extends `LettermintException`: + +| Class | When | Accessors | +| --- | --- | --- | +| `ApiException` | Any 4xx or 5xx JSON (or empty) response | `getStatus`, `getCode`, `getMessage`, `getDetails`, `getBody` | +| `AuthenticationException` | 401 | | +| `PermissionException` | 403 | | +| `NotFoundException` | 404 | | +| `ConflictException` | 409 | | +| `ValidationException` | 422 | `getErrors` (field errors) | +| `RateLimitException` | 429 | `getRetryAfter` (`Duration`) | +| `ServerException` | 5xx | | +| `TimeoutException` | No complete response within the timeout | `getTimeout` | +| `ConnectionException` | The request failed (DNS, TLS, refused, reset) | `getCause` | +| `UnexpectedResponseException` | An empty or non-JSON body where JSON was expected, or an error page such as a proxy's HTML 502 | `getStatus`, `getBodyExcerpt` | +| `RedirectException` | A 3xx response. Redirects are never followed, so tokens never go elsewhere. | `getStatus` | +| `LettermintConfigException` | A missing or unrecognised token, an invalid option or ID | | +| `LettermintValidationException` | The SDK rejected the request before sending it, such as invalid tags | `getField` | +| `WebhookVerificationException` | A webhook delivery is not genuine | `getReason` | +The subclasses of `ApiException` extend it. `getCode` and `getMessage` come from the API's error body (`{"error": {"code", "message", "details"}}` or `{"message", "errors"}`). All exceptions are in `co.lettermint.exceptions`; note that `co.lettermint.exceptions.TimeoutException` is not `java.util.concurrent.TimeoutException`. + +```java try { - lettermint.email() - .from("sender@example.com") - .to("recipient@example.com") - .subject("Test") - .send(); -} catch (ValidationException e) { - // HTTP 422 - validation errors - System.err.println("Validation failed: " + e.getMessage()); - System.err.println("Response: " + e.getResponseBody()); -} catch (HttpRequestException e) { - // Other HTTP errors - System.err.println("HTTP " + e.getStatusCode() + ": " + e.getMessage()); -} catch (LettermintException e) { - // Other SDK errors (including timeouts) - System.err.println("Error: " + e.getMessage()); + lettermint.emails().send(message, SendOptions.idempotencyKey(key)); +} catch (ValidationException error) { + System.err.println(error.getMessage() + " " + error.getErrors()); +} catch (RateLimitException error) { + // Wait error.getRetryAfter(), then retry with the same idempotency key. +} catch (TimeoutException error) { + // The outcome is unknown. Retry with the same idempotency key. +} catch (ApiException error) { + System.err.println(error.getStatus() + " " + error.getCode() + " " + error.getMessage()); } ``` -### Webhook Exceptions +Exceptions never contain request headers or tokens, and `toString()` of the client, its builder and its sub-clients shows tokens as `[redacted]`. Records that carry credentials, such as `ProjectCreatedData.apiToken()` or `WebhookSecretData.secret()`, also print them as `[redacted]`. + +## Webhooks + +Verify each webhook delivery before you trust it. Use the webhook's signing secret (`whsec_…`), not an API token, and pass the **raw** request body: the signature covers the exact bytes, so parsing and re-serializing the JSON breaks it. ```java -import co.lettermint.exceptions.webhook.*; +import co.lettermint.Webhook; +import co.lettermint.WebhookPayload; +import co.lettermint.exceptions.WebhookVerificationException; -try { - Webhook.verify(payload, signature, secret); -} catch (InvalidSignatureException e) { - // Signature doesn't match -} catch (TimestampToleranceException e) { - // Timestamp too old - System.err.println("Timestamp: " + e.getTimestamp()); - System.err.println("Tolerance: " + e.getTolerance()); -} catch (WebhookVerificationException e) { - // Other verification errors -} +Webhook webhook = new Webhook(System.getenv("LETTERMINT_WEBHOOK_SECRET")); + +WebhookPayload event = webhook.verify(rawBody, headers); +System.out.println(event.event() + " " + event.data()); ``` -## Building +`verify(rawBody, headers)` takes the body as `byte[]` or `String`, and the headers as a `Map`, a `Map>` (Spring's `HttpHeaders`, JAX-RS `MultivaluedMap`) or a lookup function such as a servlet's `request::getHeader`. It requires `X-Lettermint-Signature` and `X-Lettermint-Delivery` (header names are case-insensitive), checks the HMAC-SHA256 signature in constant time, checks that the delivery timestamp equals the signed one and is within the tolerance, and returns the payload. Otherwise it throws `WebhookVerificationException` with a `getReason()`. -### Maven +### Spring Boot -```bash -mvn clean install +```java +@RestController +class LettermintWebhookController { + private final Webhook webhook = new Webhook(System.getenv("LETTERMINT_WEBHOOK_SECRET")); + + @PostMapping("/webhooks/lettermint") + ResponseEntity receive(@RequestBody byte[] body, @RequestHeader HttpHeaders headers) { + try { + WebhookPayload event = webhook.verify(body, headers); + // Handle event.event() and event.data() here. + return ResponseEntity.noContent().build(); + } catch (WebhookVerificationException error) { + return ResponseEntity.badRequest().build(); + } + } +} ``` -### Gradle +### Servlets -```bash -./gradlew build +```java +byte[] body = request.getInputStream().readAllBytes(); +WebhookPayload event = webhook.verify(body, request::getHeader); ``` -## Testing +### Options and lower-level verification -### Maven +The default tolerance is 300 seconds in either direction. Change it with `new Webhook(secret, Duration.ofSeconds(60))`. `Duration.ZERO` accepts only the current second; it does not disable the check. A third argument takes a `java.time.Clock` for tests. A valid signature does not prevent a repeated delivery within the tolerance, so track `event.id()` if you must not process an event twice. -```bash -mvn test -``` +If the headers are not at hand, call `webhook.verifySignature(rawBody, signatureHeader, deliveryHeader)`. -### Gradle +`WebhookPayload` has `id()`, `event()` (a `WebhookEvent` such as `WebhookEvent.MESSAGE_DELIVERED`; unknown events keep their raw name), `timestamp()`, `data()` and `fields()` with every top-level field. `data(MyRecord.class)` converts the data with Jackson. + +## Types + +Request and response types are generated from the Lettermint API specification into `co.lettermint.types`, for example `SendMailRequest`, `SendMailResponse`, `DomainData` and `CursorPage`. They are records: read fields with accessors such as `domain.id()`. Unknown JSON fields are ignored. + +Enums are open: `MessageStatus`, `DomainStatus`, `WebhookEvent` and the others are classes with a constant per known value. A value that the API adds later decodes without an error and keeps its raw string: `status.value()` returns it and `status.isKnown()` tells whether this version knows it. Compare with `equals` (`MessageStatus.DELIVERED.equals(status)`) or switch on `status.value()`. + +`co.lettermint.types.Operations` describes every API operation (path, token, request and response types). + +## Requirements + +- Java 17 or later (tested on 17, 21 and 25). +- Jackson Databind 2.x, the only dependency. +- The jar has the automatic module name `co.lettermint`. +- The `User-Agent` header is `lettermint-java/`. +- Use API tokens on servers only, never in apps that you ship to users. + +## Development ```bash +./gradlew build # compile, test, javadoc and the generated-code check ./gradlew test ``` +`src/main/java/co/lettermint/types/` is generated by the private [SDK generator](https://github.com/lettermint/sdk-generator). Do not edit it by hand. With a checkout of the generator, `./gradlew generateTypes` regenerates it and `./gradlew checkGeneratedTypes` verifies it; set `LETTERMINT_SDK_GENERATOR` to the checkout (default `../sdk-generator`). Without the generator, as in CI, `checkGeneratedTypes` (part of `build`) only verifies the generated headers. + ## License MIT License - see [LICENSE](LICENSE) for details. diff --git a/UPGRADE.md b/UPGRADE.md index 9f2ef7e..8c4a5db 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -1,5 +1,475 @@ -# Upgrade To v2 +# Upgrade guide +- [Upgrade from 2.x to 3.0](#upgrade-from-2x-to-30) +- [Upgrade from 1.x to 2.0](#upgrade-from-1x-to-20) + +# Upgrade from 2.x to 3.0 + +2.x no longer receives updates, including fixes. Upgrade to 3.0 to keep getting them. + +3.0 is a new major version. The main reason is safety: in 2.x, `Lettermint.email(token)` returned one mutable, non-thread-safe `EmailEndpoint`, and the README suggested keeping it as the client. Two emails composed at the same time on it, for example in two web requests, could mix recipients, content and `Idempotency-Key`, and an email abandoned halfway (for example because `tags()` threw) leaked into the next send. 2.x also followed redirects with the sending token, could silently re-send `POST /send` after a connection failure, and treated a webhook tolerance of `0` as "no check". 3.0 stores nothing about a message on the client and fixes the rest. + +## Highlights + +- One thread-safe client: `Lettermint.builder().sendingToken(...).teamToken(...).build()`, or `Lettermint.of(token)`. It replaces `Lettermint.email()`, `Lettermint.api()`, `new Lettermint(token)`, `ApiClient` and `LettermintClient`. +- Sending is stateless: `emails().send(message, options)`, `emails().sendBatch(messages, options)` and an immutable `emails().compose()` builder. The `Idempotency-Key` is a per-call option. +- Each part uses its own token: `emails()` uses the sending token, the Team API uses the team token. The SDK never falls back to the other token. +- Typed exceptions for every outcome, including empty or HTML responses, redirects, timeouts and network failures. +- Redirects are never followed, and nothing is retried. +- A configurable timeout that covers the whole request, an injectable `java.net.http.HttpClient`, and cancellation by interrupting the thread. +- Tokens never appear in `toString()` or exception messages. +- Webhook verification is an object, `new Webhook(secret)`, and requires both signature headers. +- Typed query records and `iterate()` methods that follow `next_cursor`. +- Types are immutable records generated from the current API specification and use its names (see [Type names](#type-names)). Enums are open. +- Java 17 or later. OkHttp is no longer a dependency. + +## Requirements + +- **Java 17 or later** (2.x: Java 8). Java 8 and 11 are past their mainstream support, and 3.0 relies on Java 17: records for the generated types, and the JDK's `java.net.http` client, which since Java 16 aborts a request when its future is cancelled, so timeouts and thread interrupts really stop the request. +- The only dependency is Jackson Databind 2.x. OkHttp and its Kotlin standard library are gone; if your code used OkHttp only through this SDK, you can drop it. + +## Upgrade with a coding agent + +You can let a coding agent (Claude Code, Codex, Cursor, Copilot, …) do the upgrade. Copy this instruction into the agent from your project's root, then review its changes: + +````text +Upgrade this project from the Lettermint Java SDK 2.x (co.lettermint:lettermint) to 3.0. + +1. Change the dependency to co.lettermint:lettermint:3.0.0 in pom.xml, build.gradle(.kts) or the version catalog. 3.0 needs Java 17 or newer: check the compiler release/target, toolchains, CI workflows and Dockerfiles, and report anything older. +2. Read the upgrade guide before changing code: https://github.com/lettermint/lettermint-java/blob/main/UPGRADE.md (the sources jar, co.lettermint:lettermint:3.0.0:sources, has the Javadoc of every class). Treat the guide as the source of truth and don't guess APIs. +3. Find every use of the SDK: imports from co.lettermint, Lettermint.email(, Lettermint.api(, new Lettermint(, getClient(, EmailEndpoint, ApiClient, LettermintClient, .idempotencyKey(, .attach(, .sendBatch(, Webhook.verify(, HttpRequestException, ValidationException, InvalidSignatureException, TimestampToleranceException, co.lettermint.models, and the 2.x type names from the guide's type-name table. +4. Rewrite each use following the guide's before/after examples: + - Create one Lettermint client with Lettermint.builder().sendingToken(...), adding .teamToken(...) only where the Team API is used, and share it (for example as one Spring bean). Keep the project's existing environment variable or property names. + - Replace fluent EmailEndpoint chains with lettermint.emails().send(EmailMessage.create()...) or lettermint.emails().compose()...send(). Builders are immutable: assign the result of every setter. Never keep a half-built email in a field. + - Move idempotency keys into SendOptions.idempotencyKey(...) on send()/sendBatch(). Attachments become EmailAttachment.ofBase64(filename, base64) or EmailAttachment.of(filename, bytes), with .contentType(...) and .contentId(...). + - Team API: use the same client (lettermint.domains(), ...), typed query records instead of Map with bracket keys, record accessors (domain.id()) instead of public fields (domain.id), builders for request bodies, and the renamed methods from the guide. + - Enum constants are now objects, not strings: compare with equals() or use .value(); constant names gained underscores (SOFTBOUNCED -> SOFT_BOUNCED). + - Exceptions: switch to the 3.0 classes in co.lettermint.exceptions (ApiException and its subclasses, TimeoutException, ...). Accessors are getStatus(), getBody(), getCode(). + - Webhooks: new Webhook(secret).verify(rawBody, headers). Keep passing the raw request body, keep the secret's whsec_ prefix, and make sure the X-Lettermint-Signature and X-Lettermint-Delivery headers reach the handler. + - Rename types using the guide's type-name table; co.lettermint.models.api becomes co.lettermint.types. +5. Compile and run the tests, and fix every error. Don't send real email or call the live API while testing. +6. Finish with a summary: the files you changed, anything you could not migrate with certainty, and behaviour changes I should review. + +Never print, log or commit API tokens or webhook secrets. +```` + +## Create the client + +`Lettermint.email(...)`, `Lettermint.api(...)`, `new Lettermint(token[, baseUrl])`, `lettermint.email()`, `getClient()`, `ApiClient`, `LettermintClient` and `Endpoint` are removed. + +```java +// 2.x +EmailEndpoint email = Lettermint.email(System.getenv("LETTERMINT_PROJECT_TOKEN")); +ApiClient api = Lettermint.api(System.getenv("LETTERMINT_API_TOKEN"), "https://api.lettermint.co/v1"); +Lettermint legacy = new Lettermint(System.getenv("LETTERMINT_PROJECT_TOKEN")); + +// 3.0 +Lettermint lettermint = Lettermint.builder() + .sendingToken(System.getenv("LETTERMINT_PROJECT_TOKEN")) // for lettermint.emails() + .teamToken(System.getenv("LETTERMINT_TEAM_TOKEN")) // for the Team API + .baseUrl("https://api.lettermint.co/v1") // optional + .timeout(Duration.ofSeconds(10)) // new; default 30 seconds + .build(); +``` + +Pass one token or both. With only one, calling a part that needs the other throws `LettermintConfigException` (for example `domains.list needs teamToken; …`) before any request. + +You can also pass a token string; the SDK chooses its type by the prefix: + +```java +Lettermint lettermint = Lettermint.of("lm_team_..."); // team token +Lettermint lettermint = Lettermint.of("lm_..."); // project sending token +Lettermint lettermint = Lettermint.builder().token(token).timeout(Duration.ofSeconds(10)).build(); // with options +``` + +Any other format (SSO tokens, OAuth tokens, an empty string) throws `LettermintConfigException`; use `sendingToken(...)` or `teamToken(...)` for those. + +New options: `timeout(Duration)` (2.x had a fixed 30 seconds per connect, read and write phase; 3.0 limits the whole request) and `httpClient(HttpClient)` for a proxy, TLS settings or an executor. The client must not follow redirects. 2.x created a new OkHttp client for every `Lettermint.email(...)`/`Lettermint.api(...)` call; create the 3.0 client once and share it. + +## Send an email + +The 2.x `EmailEndpoint` was the client and a mutable builder at once, and was reset after each send. In 3.0, emails are immutable values: `EmailMessage`, or the `EmailBuilder` that `emails().compose()` returns. Each setter returns a new object and leaves the old one unchanged. Chaining works as before; if you built an email over several statements, assign the result of each setter. + +```java +// 2.x +EmailEndpoint email = Lettermint.email(token); +SendEmailResponse response = email + .from("Acme ") + .to("jane@example.com") + .subject("Welcome") + .html("

Hi Jane

") + .idempotencyKey("welcome-jane") + .send(); +String id = response.getMessageId(); + +// 3.0: builder +SendMailResponse response = lettermint.emails().compose() + .from("Acme ") + .to("jane@example.com") + .subject("Welcome") + .html("

Hi Jane

") + .send(SendOptions.idempotencyKey("welcome-jane")); +String id = response.messageId(); + +// 3.0: message value +EmailMessage message = EmailMessage.create().from("Acme ").to("jane@example.com").subject("Welcome").html("

Hi Jane

"); +lettermint.emails().send(message, SendOptions.idempotencyKey("welcome-jane")); +``` + +```java +// 2.x: statements changed the shared endpoint +email.from("hello@acme.com"); +email.to("jane@example.com"); +if (copy) email.cc("team@acme.com"); +email.subject("Hi").send(); + +// 3.0: keep the returned builder +EmailBuilder draft = lettermint.emails().compose().from("hello@acme.com").to("jane@example.com"); +if (copy) draft = draft.cc("team@acme.com"); +draft.subject("Hi").send(); +``` + +A base builder can now be shared safely, also between threads: + +```java +EmailBuilder welcome = lettermint.emails().compose().from("Acme ").subject("Welcome"); +welcome.to("jane@example.com").html(janeHtml).send(); +welcome.to("john@example.com").html(johnHtml).send(SendOptions.idempotencyKey("welcome-john")); +``` + +### Changed builder methods + +| 2.x (`EmailEndpoint`) | 3.0 (`EmailBuilder` and `EmailMessage`) | +| --- | --- | +| Setters change the endpoint and return it | Return a new builder or message | +| `.idempotencyKey(key).send()` | `.send(SendOptions.idempotencyKey(key))` | +| `.send()` returns `SendEmailResponse` (`getMessageId()`, `getStatus()`) | `.send()` returns `SendMailResponse` (`messageId()`, `status()` as `MessageStatus`, `sandbox()`, `sandboxResult()`, `scheduledAt()`) | +| `.attach(filename, base64)`, `.attach(filename, base64, contentId)`, `.attach(filename, base64, contentId, contentType)` | `.attach(EmailAttachment.ofBase64(filename, base64).contentId(id).contentType(type))`, or `EmailAttachment.of(filename, bytes)`, which base64-encodes for you | +| `.header(name, value)` | Removed; pass every header to `.headers(map)` | +| `.metadata(Map)`, `.metadata(key, value)` | `.metadata(Map)` (the API stores strings) | +| `.tags(MessageTag...)` with `co.lettermint.models.MessageTag`, `.tags(Map...)` | `.tags(MessageTagInput...)` or `.tags(Collection)` with `co.lettermint.types.MessageTagInput` | +| `.settings(Map)` | `.settings(SendMailRequestSettings)` | +| `.sandboxResult(String)` | `.sandboxResult(SandboxResult)` (`SandboxResult.of("…")` for any value) | +| `.scheduledAt(String)` | `.scheduledAt(String)` or `.scheduledAt(Instant)` | +| `.html(null)`, `.text(null)` | `null` removes the field; so do `tag(null)`, `route(null)` and the other single-value setters | +| Invalid tags threw `IllegalArgumentException` | Throw `LettermintValidationException` (with `getField()`); the builder is unchanged | +| — | `builder.build()` returns the `EmailMessage`; `message.toRequest()` the wire format | + +Unchanged setters: `from`, `to`, `cc`, `bcc`, `replyTo` (each replaces its list), `subject`, `html`, `text`, `headers`, `route`, `tag`. + +## Batch sending and ping + +```java +// 2.x +SendMailRequest request = new SendMailRequest(); +request.fromValue = "hello@acme.com"; +request.to = List.of("jane@example.com"); +request.subject = "Hi"; +Lettermint.email(token).idempotencyKey("batch-1").sendBatch(List.of(request)); +Lettermint.email(token).ping(); +Lettermint.api(token).ping(); + +// 3.0 +lettermint.emails().sendBatch(List.of( + EmailMessage.create().from("hello@acme.com").to("jane@example.com").subject("Hi"), + builder.build()), SendOptions.idempotencyKey("batch-1")); +lettermint.emails().ping(); // sending token +lettermint.ping(); // team token if configured, otherwise the sending token +``` + +## Team API + +The endpoint groups move from `Lettermint.api(token).x()` to `lettermint.x()`. Query parameters are typed records instead of `Map` with bracket keys, and every list has an `iterate()` method that follows `next_cursor`. + +```java +// 2.x +ApiClient api = Lettermint.api(token); +DomainIndexResponse page = api.domains().list(Map.of("page[size]", "10", "filter[status]", "verified")); +for (DomainListData domain : page.data) { System.out.println(domain.domain); } + +// 3.0 +CursorPage page = lettermint.domains().list(ListDomainsQuery.builder().pageSize(10).filterStatus(DomainStatus.VERIFIED).build()); +for (DomainListData domain : lettermint.domains().iterate(ListDomainsQuery.builder().filterStatus(DomainStatus.VERIFIED).build())) { + System.out.println(domain.domain()); +} +``` + +| 2.x (`api = Lettermint.api(token)`) | 3.0 (`lettermint = Lettermint.builder().teamToken(token).build()`) | +| --- | --- | +| `api.ping()` | `lettermint.ping()` | +| `api.blockedFileTypes()` | `lettermint.blockedFileTypes()` | +| `api.analytics(AnalyticsRequest)` | `lettermint.analytics(AnalyticsQuery)` | +| `api.domains().list(map)` | `lettermint.domains().list(ListDomainsQuery)`, `lettermint.domains().iterate(query)` | +| `api.domains().create(payload)` | `lettermint.domains().create(payload)` | +| `api.domains().retrieve(id)` | `lettermint.domains().retrieve(id)` or `retrieve(id, GetDomainQuery)` (`include`: `GetDomainQueryIncludeItem.DNS_RECORDS`) | +| `api.domains().delete(id)` | `lettermint.domains().delete(id)` | +| `api.domains().verifyDnsRecords(id)` | `lettermint.domains().verifyDnsRecords(id)` | +| `api.domains().verifyDnsRecord(id, recordId)` | `lettermint.domains().verifyDnsRecord(id, recordId)` | +| `api.domains().updateProjects(id, payload)` | `lettermint.domains().updateProjects(id, payload)` | +| `api.messages().list(map)` | `lettermint.messages().list(ListMessagesQuery)`, `lettermint.messages().iterate(query)` | +| `api.messages().retrieve(id)` | `lettermint.messages().retrieve(id)` | +| `api.messages().events(id[, map])` | `lettermint.messages().events(id[, ListMessageEventsQuery])`, `lettermint.messages().iterateEvents(id[, query])` | +| `api.messages().source(id)` / `.html(id)` / `.text(id)` | unchanged, on `lettermint.messages()` | +| `api.messages().reschedule(id, payload)` | `lettermint.messages().reschedule(id, payload)`; accepts either token | +| `api.messages().cancel(id)` | `lettermint.messages().cancel(id)`; accepts either token | +| `api.messages().process(id)` | `lettermint.messages().process(id[, SendOptions.idempotencyKey(key)])` | +| `api.projects().list(map)` | `lettermint.projects().list(ListProjectsQuery)`, `lettermint.projects().iterate(query)` | +| `api.projects().create(payload)` | `lettermint.projects().create(payload)` | +| `api.projects().retrieve(id)` | `lettermint.projects().retrieve(id[, GetProjectQuery])` | +| `api.projects().update(id, payload)` | `lettermint.projects().update(id, payload)` | +| `api.projects().delete(id)` | `lettermint.projects().delete(id)` | +| `api.projects().rotateToken(id)` | `lettermint.projects().rotateToken(id)` (deprecated by the API) | +| `api.projects().routes(projectId[, map])` | `lettermint.routes().list(projectId[, ListRoutesQuery])`, `lettermint.routes().iterate(projectId[, query])` | +| `api.projects().createRoute(projectId, payload)` | `lettermint.routes().create(projectId, payload)` | +| `api.projects().retrieveReportForwarding(id)` | `lettermint.projects().reportForwarding().retrieve(id)` | +| `api.projects().updateReportForwarding(id, payload)` | `lettermint.projects().reportForwarding().update(id, payload)` | +| `api.projects().deleteReportForwarding(id)` | `lettermint.projects().reportForwarding().delete(id)` | +| `api.projects().verifyReportForwarding(id, payload)` | `lettermint.projects().reportForwarding().verify(id, payload)` | +| `api.projects().resendReportForwardingCode(id)` | `lettermint.projects().reportForwarding().resendCode(id)` | +| `api.routes().retrieve(id)` | `lettermint.routes().retrieve(id[, GetRouteQuery])` | +| `api.routes().update(id, payload)` | `lettermint.routes().update(id, payload)` | +| `api.routes().delete(id)` | `lettermint.routes().delete(id)` | +| `api.routes().verifyInboundDomain(id)` | `lettermint.routes().verifyInboundDomain(id)` | +| `api.stats().retrieve(map)` | `lettermint.stats().retrieve(GetStatsQuery.builder().from(...).to(...).build())` | +| `api.suppressions().list(map)` | `lettermint.suppressions().list(ListSuppressionsQuery)`, `lettermint.suppressions().iterate(query)` | +| `api.suppressions().create(payload)` | `lettermint.suppressions().create(payload)` | +| `api.suppressions().delete(id)` | `lettermint.suppressions().delete(id)` | +| `api.team().retrieve()` | `lettermint.team().retrieve([GetTeamQuery])` | +| `api.team().update(payload)` | `lettermint.team().update(payload)` | +| `api.team().usage([map])` | `lettermint.team().usage()` (the endpoint takes no parameters) | +| `api.team().roles()` | `lettermint.team().roles()` | +| `api.team().members([map])` | `lettermint.team().members().list([ListTeamMembersQuery])`, `lettermint.team().members().iterate([query])` | +| `api.team().member(userId)` | `lettermint.team().members().retrieve(userId)` | +| `api.team().updateMemberAssignment(userId, payload)` | `lettermint.team().members().updateAssignment(userId, payload)` | +| `api.webhooks().list(map)` | `lettermint.webhooks().list(ListWebhooksQuery)`, `lettermint.webhooks().iterate(query)` | +| `api.webhooks().create(payload)` | `lettermint.webhooks().create(payload)` | +| `api.webhooks().retrieve(id)` | `lettermint.webhooks().retrieve(id)` | +| `api.webhooks().update(id, payload)` | `lettermint.webhooks().update(id, payload)` | +| `api.webhooks().delete(id)` | `lettermint.webhooks().delete(id)` | +| `api.webhooks().test(id)` | `lettermint.webhooks().test(id)` | +| `api.webhooks().regenerateSecret(id)` | `lettermint.webhooks().regenerateSecret(id)` | +| `api.webhooks().deliveries(id[, map])` | `lettermint.webhooks().deliveries().list(id[, ListWebhookDeliveriesQuery])`, `lettermint.webhooks().deliveries().iterate(id[, query])` | +| `api.webhooks().delivery(id, deliveryId)` | `lettermint.webhooks().deliveries().retrieve(id, deliveryId)` | + +Every method also has an overload with a last `RequestOptions` argument (`RequestOptions.timeout(Duration)`); `messages().process()` takes `SendOptions`. + +### Query parameters + +Query records have one builder method per parameter, named after the wire name in camel case. Arrays of values are joined with commas, arrays of objects are indexed, and booleans are sent as `1`/`0`. + +| 2.x | 3.0 | +| --- | --- | +| `Map.of("page[size]", "30", "page[cursor]", c)` | `ListDomainsQuery.builder().pageSize(30).pageCursor(c).build()` | +| `Map.of("filter[status]", "verified")` | `.filterStatus(DomainStatus.VERIFIED)` | +| `Map.of("sort", "-created_at,domain")` | `.sort(List.of(ListDomainsQuerySortItem.CREATED_AT_DESC, ListDomainsQuerySortItem.DOMAIN))` | +| `Map.of("filter[enabled]", "true")` | `ListWebhooksQuery.builder().filterEnabled(true)` | +| `Map.of("filter[tags][0][name]", "a", "filter[tags][0][value]", "b")` | `ListMessagesQuery.builder().filter(ListMessagesQueryFilter.builder().tags(List.of(ListMessagesQueryFilterTagsItem.builder().name("a").value("b").build())).build())` | +| webhooks: `Map.of("cursor", c)` | unchanged wire name: `ListWebhooksQuery.builder().cursor(c)` (these lists use `cursor`, not `page[cursor]`) | + +### Path parameters + +IDs are still URL-encoded. An empty or null ID, `.` or `..` now throws `LettermintConfigException` before the request. + +### Message lists + +2.x typed message and event lists with a `meta` map. The API returns a flat cursor page, which 3.0 types as `CursorPage`: read `page.nextCursor()`, or use `iterate()`. + +## Models + +The generated types moved from `co.lettermint.models.api` to `co.lettermint.types` and became immutable records: + +```java +// 2.x: public mutable fields +DomainData domain = api.domains().retrieve(id); +String name = domain.domain; +StoreWebhookData payload = new StoreWebhookData(); +payload.name = "Hook"; +payload.url = "https://acme.com/hook"; +payload.events = List.of(WebhookEvent.MESSAGE_DELIVERED); + +// 3.0: accessors and builders +String name = lettermint.domains().retrieve(id).domain(); +StoreWebhookData payload = StoreWebhookData.builder() + .name("Hook") + .url("https://acme.com/hook") + .events(List.of(WebhookEvent.MESSAGE_DELIVERED)) + .build(); +``` + +- Field access becomes an accessor (`domain.domain` → `domain.domain()`; 2.x `fromValue` → `from()`). Requests are built with `X.builder()…build()`, `toBuilder()` or the record constructor. +- Lists and maps in records are unmodifiable. +- Integers are `Long` and numbers `Double` (builders also take `long` and `double`). +- **Enums are open objects, not strings.** In 2.x, `MessageStatus.DELIVERED` was the `String` `"delivered"` and fields were `String`. In 3.0 fields are typed (`MessageStatus status()`), constants are `MessageStatus` instances, and a value the API adds later decodes without an error: `status.value()` returns the raw string and `status.isKnown()` tells whether this version knows it. Compare with `MessageStatus.DELIVERED.equals(status)` or switch on `status.value()`; build a value with `MessageStatus.of("…")`. +- **Enum constant names gained underscores**: `SOFTBOUNCED` → `SOFT_BOUNCED`, `HARDBOUNCED` → `HARD_BOUNCED`, `SPAMCOMPLAINT` → `SPAM_COMPLAINT`, `POLICYREJECTED` → `POLICY_REJECTED`, `WebhookEvent.MESSAGEDELIVERED` → `MESSAGE_DELIVERED`, and so on. Sort values with a leading `-` end in `_DESC` (`-created_at` → `CREATED_AT_DESC`). +- `OptionalNullable` moved to `co.lettermint.types`: `OptionalNullable.nullValue()` → `ofNull()`, `getValue()` → `value()`. Request builders create it for you: an optional and nullable field that you leave unset is omitted, and `null` sends JSON `null`. + +## Errors + +`HttpRequestException` and the 2.x `ValidationException` are replaced. Every SDK exception still extends `co.lettermint.exceptions.LettermintException` (unchecked). + +| Situation | 2.x | 3.0 | +| --- | --- | --- | +| HTTP 400 and other 4xx | `HttpRequestException` (`getStatusCode()`, `getResponseBody()`) | `ApiException` (`getStatus()`, `getCode()`, `getMessage()`, `getDetails()`, `getBody()`) | +| HTTP 401 | `HttpRequestException` | `AuthenticationException` | +| HTTP 403 | `HttpRequestException` | `PermissionException` | +| HTTP 404 | `HttpRequestException` | `NotFoundException` | +| HTTP 409 | `HttpRequestException` | `ConflictException` | +| HTTP 422 | `ValidationException` (`getResponseBody()` as a string) | `ValidationException` (`getErrors()` field errors, `getBody()`) | +| HTTP 429 | `HttpRequestException` | `RateLimitException` (`getRetryAfter()` as a `Duration`) | +| HTTP 5xx | `HttpRequestException` | `ServerException` | +| Empty or invalid JSON body, HTML error page | `LettermintException` ("Request failed: …") or `HttpRequestException` | `UnexpectedResponseException` (`getStatus()`, `getBodyExcerpt()`) | +| Redirect (3xx) | followed, also to another host, with the token | `RedirectException` (`getStatus()`); never followed | +| Timeout | `LettermintException` ("Request timed out") | `co.lettermint.exceptions.TimeoutException` (`getTimeout()`); covers the whole request | +| Network failure | `LettermintException` ("Request failed: …"); OkHttp could also re-send the request | `ConnectionException`; never retried | +| Invalid tags | `IllegalArgumentException` | `LettermintValidationException` (`getField()`) | +| Missing or wrong token, bad option | `IllegalArgumentException` | `LettermintConfigException` | + +Property renames: `getStatusCode()` → `getStatus()`, `getResponseBody()` (a string) → `getBody()` (decoded JSON). `getCode()` is new and comes from `{"error": {"code"}}` or a string `error` field. + +```java +// 2.x +try { + email.send(); +} catch (ValidationException e) { + log.warn(e.getResponseBody()); +} catch (HttpRequestException e) { + if (e.getStatusCode() == 429) retryLater(); +} + +// 3.0 +try { + builder.send(); +} catch (ValidationException e) { + log.warn("{} {}", e.getMessage(), e.getErrors()); +} catch (RateLimitException e) { + retryLater(e.getRetryAfter()); +} +``` + +The SDK does not retry requests. Pass an idempotency key when you retry a send. Interrupting the calling thread aborts the request and throws `java.util.concurrent.CancellationException`, not an SDK exception. + +## Webhooks + +The static `Webhook.verify(payload, signature, secret[, tolerance])` is replaced by a verifier object. `verify()` now takes the raw body and the request headers, requires both `X-Lettermint-Signature` and `X-Lettermint-Delivery`, and returns a `WebhookPayload` instead of `Map`. + +```java +// 2.x +Map payload = Webhook.verify(rawPayload, signatureHeader, secret); +Map payload = Webhook.verify(rawPayload, signatureHeader, secret, 600); +String event = (String) payload.get("event"); + +// 3.0 +Webhook webhook = new Webhook(secret); // create once +Webhook webhook = new Webhook(secret, Duration.ofSeconds(600)); +WebhookPayload payload = webhook.verify(rawBody, headers); // Map, Map>, or request::getHeader +WebhookPayload payload = webhook.verifySignature(rawBody, signatureHeader, deliveryHeader); +WebhookEvent event = payload.event(); +Map all = payload.fields(); +``` + +- The body may be a `String` or the raw `byte[]`. +- `X-Lettermint-Delivery` must be present and equal the signed timestamp. 2.x ignored it. +- Every `v1` signature in the header is checked, so key rotation works; 2.x used only the last one. +- A tolerance of `0` now accepts only the current second; 2.x skipped the timestamp check for `0` or less. A negative tolerance or an empty secret throws `LettermintConfigException` (2.x: `WebhookVerificationException` for an empty secret). +- `InvalidSignatureException` and `TimestampToleranceException` are removed. Every failure is a `co.lettermint.exceptions.WebhookVerificationException` (it moved out of `co.lettermint.exceptions.webhook`) with `getReason()`: `SIGNATURE_HEADER_MISSING`, `SIGNATURE_HEADER_MALFORMED`, `DELIVERY_HEADER_MISSING`, `DELIVERY_TIMESTAMP_MISMATCH`, `TIMESTAMP_OUT_OF_TOLERANCE`, `SIGNATURE_MISMATCH`, `BODY_INVALID` or `PAYLOAD_INVALID` (`reason.code()` gives the shared code, such as `signature_mismatch`). +- `Webhook` moved from `co.lettermint.webhooks` to `co.lettermint`. + +## Type names + +The types are generated from the API specification of lettermint#2582 and use its names. They moved from `co.lettermint.models.api` to `co.lettermint.types`. Some shapes also changed: + +- Java has no type aliases, so list responses are `CursorPage` and `sendBatch()` returns `List`. +- `SendMailResponse` has every field of a pending and a scheduled send; check `status()`. `PendingSendMailResponse` and `ScheduledSendMailResponse` describe the two cases. +- `MessageTag` (in `co.lettermint.types`) describes tags in responses; `MessageTagInput` describes tags you send. +- `SuppressionStoreResponse.message()` is a `String` (2.x: `Object`). + +These classes keep their name: `AnalyticsResponse`, `AttachmentDelivery`, `BuiltInTeamRole`, `DeliveryMode`, `DkimMode`, `DnsRecordPurpose`, `DnsRecordStatus`, `DnsVerificationScope`, `DomainData`, `DomainDnsRecordData`, `DomainListData`, `DomainStatus`, `GetReportForwardingResponse`, `InitialRoutes`, `MessageAttachmentData`, `MessageData`, `MessageEventData`, `MessageEventType`, `MessageListData`, `MessageRecipientData`, `MessageStatsData`, `MessageStatus`, `MessageType`, `OptionalNullable`, `Plan`, `ProcessInboundMessageResponse`, `ProjectAccessScope`, `ProjectCreatedData`, `ProjectData`, `ProjectListData`, `RbacConflictCode`, `RbacPermission`, `RecordType`, `ReportForwardingRequest`, `ReportForwardingResource`, `RescheduleMessageRequest`, `ResendReportForwardingCodeResponse`, `RouteData`, `RouteListData`, `RouteStatisticData`, `RouteType`, `SandboxResult`, `SendMailRequest`, `SendMailResponse`, `SpamSymbol`, `StatsDailyData`, `StatsData`, `StatsInboundData`, `StatsTotalsData`, `StatsTypeData`, `StoreDomainData`, `StoreProjectData`, `StoreRouteData`, `StoreSuppressionData`, `StoreWebhookData`, `SuppressedRecipientData`, `SuppressionAppliesTo`, `SuppressionReason`, `SuppressionScope`, `SuppressionSourceMessageData`, `SuppressionStoreResponse`, `SuppressionType`, `TeamAddonData`, `TeamData`, `TeamMemberData`, `TeamMemberProjectAccessData`, `TeamRoleData`, `TeamType`, `TeamUsageDetailData`, `TeamUsagePeriodData`, `TlsPolicy`, `UpdateDomainProjectsData`, `UpdateProjectData`, `UpdateReportForwardingResponse`, `UpdateRouteData`, `UpdateRouteInboundSettingsData`, `UpdateRouteSettingsData`, `UpdateTeamData`, `UpdateTeamMemberAssignmentData`, `UpdateWebhookData`, `VerifyReportForwardingRequest`, `VerifyReportForwardingResponse`, `WebhookBasicAuthData`, `WebhookData`, `WebhookDeliveryData`, `WebhookDeliveryListData`, `WebhookDeliveryModeFilter`, `WebhookDeliveryStatus`, `WebhookEvent`, `WebhookListData`, `WebhookScope`, `WebhookSecretData`. + +| 2.x (`co.lettermint.models.api`) | 3.0 (`co.lettermint.types`) | +| --- | --- | +| `AnalyticsRequest` | `AnalyticsQuery` | +| `AnalyticsRequestFiltersItem` | `AnalyticsFilter` | +| `AnalyticsRequestSort` | `AnalyticsSort` | +| `AnalyticsResponseMeta` | `AnalyticsMeta` | +| `AnalyticsResponseMetaComparison` | `AnalyticsMetaComparison` | +| `AnalyticsResponsePagination` | `AnalyticsPagination` | +| `AnalyticsResponsePayload` | `AnalyticsResults` | +| `AnalyticsResponsePayloadBreakdownItem` | `AnalyticsBreakdownRow` | +| `AnalyticsResponsePayloadSummary` | `AnalyticsSummary` | +| `AnalyticsResponsePayloadTimeSeriesItem, AnalyticsResponsePayloadBreakdownItemTrendItem` | `AnalyticsTimeSeriesPoint` | +| AnalyticsResponsePayload…Metrics, …PreviousMetrics (8 classes) | `AnalyticsMetricValues` | +| AnalyticsResponsePayload…Previous (4 classes) | `AnalyticsComparisonValues` | +| AnalyticsResponsePayload…RateBases, …PreviousRateBases (8 classes) | `AnalyticsRateBases` | +| AnalyticsResponsePayload…RateBases…Rate (56 classes, for example AnalyticsResponsePayloadSummaryRateBasesBounceRate) | `AnalyticsRateBase` | +| `BlockedFileTypesResponse` | `BlockedFileTypes` | +| `CancelScheduledMessageResponse` | `ScheduledMessage` | +| `CursorPaginator` | `CursorPage` | +| `DomainDestroyResponse` | `MessageResponse` | +| `DomainIndexResponse` | `CursorPage` | +| `DomainUpdateProjectsResponse` | `DomainMutationResponse` | +| `DomainVerifyDnsRecordsResponse` | `DnsVerificationSuccessResponse` | +| `DomainVerifySpecificDnsRecordResponse` | `MessageResponse` | +| `MessageEventsResponse` | `CursorPage` | +| `MessageIndexResponse` | `CursorPage` | +| `ProjectDestroyResponse` | `MessageResponse` | +| `ProjectIndexResponse` | `CursorPage` | +| `ProjectRotateTokenResponse` | `RotateProjectTokenResponse` | +| `ProjectStoreResponse` | `ProjectCreatedData` | +| `ProjectUpdateResponse` | `ProjectMutationResponse` | +| `RescheduleMessageResponse` | `ScheduledMessage` | +| `RouteDestroyResponse` | `MessageResponse` | +| `RouteIndexResponse` | `CursorPage` | +| `RouteStoreResponse` | `RouteMutationResponse` | +| `RouteUpdateResponse` | `RouteMutationResponse` | +| `RouteVerifyInboundDomainResponse` | `InboundDomainVerificationResponse` | +| `SuppressionDestroyResponse` | `DeleteSuppressionResponse` | +| `SuppressionIndexResponse` | `CursorPage` | +| `TeamMembersResponse` | `CursorPage` | +| `TeamRolesResponse` | `TeamRoleListResponse` | +| `TeamUpdateResponse` | `TeamMutationResponse` | +| `UpdateReportForwardingRequest` | `ReportForwardingRequest` | +| `WebhookDeliveriesResponse` | `CursorPage` | +| `WebhookDestroyResponse` | `MessageResponse` | +| `WebhookIndexResponse` | `CursorPage` | +| `WebhookRegenerateSecretResponse` | `WebhookSecretResponse` | +| `WebhookStoreResponse` | `WebhookSecretResponse` | +| `WebhookTestResponse` | `TestWebhookResponse` | +| `WebhookUpdateResponse` | `WebhookMutationResponse` | + +| 2.x (`co.lettermint.models`) | 3.0 | +| --- | --- | +| `SendEmailResponse` | `co.lettermint.types.SendMailResponse` | +| `MessageTag` | `co.lettermint.types.MessageTagInput` | +| `Attachment` | `co.lettermint.EmailAttachment` | + +### Removed types + +lettermint#2582 removed these schemas from the API specification: + +| 2.x | 3.0 | +| --- | --- | +| `AnalyticsResponseData` | Removed. Use `AnalyticsResponse` (`data()` is `AnalyticsResults`). | +| `StatsRequestData` | Removed. Use `GetStatsQuery`, the parameters of `stats().retrieve()`. | +| Message list `meta` (`MessageIndexResponse.meta`, `MessageEventsResponse.meta`) | Removed; 2.x had no class for it, only a `Map` field. Lists are flat `CursorPage`. | +| `SuppressionStoreResponseMessage1` | Removed; not exported by 2.x. `SuppressionStoreResponse.message()` is a `String`. | + +### Removed classes and helpers + +| 2.x | 3.0 | +| --- | --- | +| `co.lettermint.Lettermint`: `new Lettermint(token[, baseUrl])`, `email()`, `getClient()`, static `email(token[, baseUrl])`, static `api(token[, baseUrl])` | `co.lettermint.Lettermint`: `Lettermint.builder()…build()`, `Lettermint.of(token)`, `emails()`, `domains()`, … | +| `co.lettermint.api.ApiClient` and its nested `DomainsEndpoint`, `MessagesEndpoint`, `ProjectsEndpoint`, `RoutesEndpoint`, `StatsEndpoint`, `SuppressionsEndpoint`, `TeamEndpoint`, `WebhooksEndpoint` | `Lettermint` with `Domains`, `Messages`, `Projects` (and `ReportForwarding`), `Routes`, `Stats`, `Suppressions`, `Team` (and `TeamMembers`), `Webhooks` (and `WebhookDeliveries`) | +| `co.lettermint.client.LettermintClient` (`get`, `post`, `put`, `patch`, `delete`, `getRaw`, `getObjectMapper`) and `LettermintClient.AuthMode` | Removed. Every documented endpoint has a method. | +| `co.lettermint.endpoints.EmailEndpoint` | `Emails` (`lettermint.emails()`) and `EmailBuilder` (`emails().compose()`), plus `EmailMessage` | +| `co.lettermint.endpoints.Endpoint` | Removed | +| `co.lettermint.BuildInfo` | No longer public; the version is in the jar manifest and the `User-Agent` | +| `co.lettermint.exceptions.HttpRequestException` | `ApiException` and its subclasses | +| `co.lettermint.exceptions.ValidationException` (2.x) | `ValidationException` (3.0, extends `ApiException`) | +| `co.lettermint.exceptions.webhook.WebhookVerificationException`, `InvalidSignatureException`, `TimestampToleranceException` | `co.lettermint.exceptions.WebhookVerificationException` with `getReason()` | +| `co.lettermint.webhooks.Webhook` (static `verify`) | `co.lettermint.Webhook` (`new Webhook(secret).verify(…)`) | +| `co.lettermint.models.Attachment`, `MessageTag`, `SendEmailResponse` | See the table above | + +# Upgrade from 1.x to 2.0 This guide covers upgrading from the latest released v1 Java SDK to v2. ## Highlights From 61144d7e1b0f8ba525b4d1a82e4ed809ed7497a3 Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Sun, 4 Oct 2026 00:48:41 +0200 Subject: [PATCH 6/6] chore: regenerate types from the merged API spec The spec at lettermint/lettermint@0b4ecbdd23 (main, the #2582 merge) is identical to the previous pin; only the generated file headers change. --- src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java | 2 +- .../java/co/lettermint/types/AnalyticsCatalogueDimension.java | 2 +- .../co/lettermint/types/AnalyticsCatalogueGroupDimension.java | 2 +- src/main/java/co/lettermint/types/AnalyticsComparison.java | 2 +- .../java/co/lettermint/types/AnalyticsComparisonValues.java | 2 +- src/main/java/co/lettermint/types/AnalyticsDimension.java | 2 +- src/main/java/co/lettermint/types/AnalyticsFilter.java | 2 +- src/main/java/co/lettermint/types/AnalyticsFilterOperator.java | 2 +- src/main/java/co/lettermint/types/AnalyticsGroupDimension.java | 2 +- src/main/java/co/lettermint/types/AnalyticsInterval.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMeta.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java | 2 +- .../lettermint/types/AnalyticsMetaCollectionCompleteness.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMetaComparison.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMetric.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMetricChange.java | 2 +- src/main/java/co/lettermint/types/AnalyticsMetricValues.java | 2 +- src/main/java/co/lettermint/types/AnalyticsPagination.java | 2 +- src/main/java/co/lettermint/types/AnalyticsQuery.java | 2 +- src/main/java/co/lettermint/types/AnalyticsRateBase.java | 2 +- src/main/java/co/lettermint/types/AnalyticsRateBases.java | 2 +- src/main/java/co/lettermint/types/AnalyticsResponse.java | 2 +- src/main/java/co/lettermint/types/AnalyticsResults.java | 2 +- src/main/java/co/lettermint/types/AnalyticsSection.java | 2 +- src/main/java/co/lettermint/types/AnalyticsSort.java | 2 +- src/main/java/co/lettermint/types/AnalyticsSortDirection.java | 2 +- src/main/java/co/lettermint/types/AnalyticsSummary.java | 2 +- src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java | 2 +- src/main/java/co/lettermint/types/ApiError.java | 2 +- src/main/java/co/lettermint/types/ApiErrorDetail.java | 2 +- src/main/java/co/lettermint/types/AttachmentDelivery.java | 2 +- src/main/java/co/lettermint/types/BlockedFileTypes.java | 2 +- src/main/java/co/lettermint/types/BuiltInTeamRole.java | 2 +- src/main/java/co/lettermint/types/Copies.java | 2 +- src/main/java/co/lettermint/types/CursorPage.java | 2 +- .../java/co/lettermint/types/DeleteSuppressionResponse.java | 2 +- .../co/lettermint/types/DeleteSuppressionResponseStatus.java | 2 +- src/main/java/co/lettermint/types/DeliveryMode.java | 2 +- src/main/java/co/lettermint/types/DkimMode.java | 2 +- src/main/java/co/lettermint/types/DmarcPolicy.java | 2 +- src/main/java/co/lettermint/types/DnsRecordPurpose.java | 2 +- src/main/java/co/lettermint/types/DnsRecordStatus.java | 2 +- .../lettermint/types/DnsRecordVerificationFailureResponse.java | 2 +- src/main/java/co/lettermint/types/DnsVerificationError.java | 2 +- .../java/co/lettermint/types/DnsVerificationFailedRecord.java | 2 +- .../co/lettermint/types/DnsVerificationFailureResponse.java | 2 +- .../java/co/lettermint/types/DnsVerificationResultData.java | 2 +- .../types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java | 2 +- src/main/java/co/lettermint/types/DnsVerificationScope.java | 2 +- .../co/lettermint/types/DnsVerificationSuccessResponse.java | 2 +- src/main/java/co/lettermint/types/DomainData.java | 2 +- src/main/java/co/lettermint/types/DomainDataProjectsItem.java | 2 +- src/main/java/co/lettermint/types/DomainDnsRecordData.java | 2 +- src/main/java/co/lettermint/types/DomainListData.java | 2 +- src/main/java/co/lettermint/types/DomainMutationResponse.java | 2 +- src/main/java/co/lettermint/types/DomainStatus.java | 2 +- src/main/java/co/lettermint/types/ErrorMessage.java | 2 +- src/main/java/co/lettermint/types/GetDomainQuery.java | 2 +- .../java/co/lettermint/types/GetDomainQueryIncludeItem.java | 2 +- src/main/java/co/lettermint/types/GetProjectQuery.java | 2 +- .../java/co/lettermint/types/GetProjectQueryIncludeItem.java | 2 +- .../java/co/lettermint/types/GetReportForwardingResponse.java | 2 +- src/main/java/co/lettermint/types/GetRouteQuery.java | 2 +- src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java | 2 +- src/main/java/co/lettermint/types/GetStatsQuery.java | 2 +- src/main/java/co/lettermint/types/GetTeamQuery.java | 2 +- src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java | 2 +- .../java/co/lettermint/types/InboundDomainVerification.java | 2 +- .../co/lettermint/types/InboundDomainVerificationResponse.java | 2 +- src/main/java/co/lettermint/types/InitialRoutes.java | 2 +- src/main/java/co/lettermint/types/ListDomainsQuery.java | 2 +- src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListMessageEventsQuery.java | 2 +- .../co/lettermint/types/ListMessageEventsQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListMessagesQuery.java | 2 +- src/main/java/co/lettermint/types/ListMessagesQueryFilter.java | 2 +- .../co/lettermint/types/ListMessagesQueryFilterTagsItem.java | 2 +- .../java/co/lettermint/types/ListMessagesQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListProjectsQuery.java | 2 +- .../java/co/lettermint/types/ListProjectsQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListRoutesQuery.java | 2 +- src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListSuppressionsQuery.java | 2 +- .../java/co/lettermint/types/ListSuppressionsQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListTeamMembersQuery.java | 2 +- .../java/co/lettermint/types/ListWebhookDeliveriesQuery.java | 2 +- .../co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/ListWebhooksQuery.java | 2 +- .../java/co/lettermint/types/ListWebhooksQuerySortItem.java | 2 +- src/main/java/co/lettermint/types/MessageAttachmentData.java | 2 +- src/main/java/co/lettermint/types/MessageAttachmentInput.java | 2 +- src/main/java/co/lettermint/types/MessageData.java | 2 +- src/main/java/co/lettermint/types/MessageEventData.java | 2 +- src/main/java/co/lettermint/types/MessageEventType.java | 2 +- src/main/java/co/lettermint/types/MessageListData.java | 2 +- src/main/java/co/lettermint/types/MessageRecipientData.java | 2 +- src/main/java/co/lettermint/types/MessageResponse.java | 2 +- src/main/java/co/lettermint/types/MessageStatsData.java | 2 +- src/main/java/co/lettermint/types/MessageStatus.java | 2 +- src/main/java/co/lettermint/types/MessageTag.java | 2 +- src/main/java/co/lettermint/types/MessageTagInput.java | 2 +- src/main/java/co/lettermint/types/MessageType.java | 2 +- src/main/java/co/lettermint/types/Operations.java | 2 +- src/main/java/co/lettermint/types/OptionalNullable.java | 2 +- src/main/java/co/lettermint/types/PendingSendMailResponse.java | 2 +- src/main/java/co/lettermint/types/Plan.java | 2 +- .../java/co/lettermint/types/ProcessInboundMessageConflict.java | 2 +- .../co/lettermint/types/ProcessInboundMessageConflictError.java | 2 +- .../types/ProcessInboundMessageConflictErrorCode.java | 2 +- .../java/co/lettermint/types/ProcessInboundMessageResponse.java | 2 +- .../java/co/lettermint/types/ProcessInboundMessageResult.java | 2 +- src/main/java/co/lettermint/types/ProjectAccessScope.java | 2 +- src/main/java/co/lettermint/types/ProjectCreatedData.java | 2 +- src/main/java/co/lettermint/types/ProjectData.java | 2 +- src/main/java/co/lettermint/types/ProjectListData.java | 2 +- src/main/java/co/lettermint/types/ProjectMutationResponse.java | 2 +- src/main/java/co/lettermint/types/QueryParameters.java | 2 +- src/main/java/co/lettermint/types/RbacConflictCode.java | 2 +- src/main/java/co/lettermint/types/RbacConflictException.java | 2 +- .../java/co/lettermint/types/RbacConflictExceptionError.java | 2 +- src/main/java/co/lettermint/types/RbacPermission.java | 2 +- src/main/java/co/lettermint/types/RecordType.java | 2 +- src/main/java/co/lettermint/types/ReportForwardingRequest.java | 2 +- src/main/java/co/lettermint/types/ReportForwardingResource.java | 2 +- src/main/java/co/lettermint/types/RescheduleMessageRequest.java | 2 +- .../co/lettermint/types/ResendReportForwardingCodeResponse.java | 2 +- .../java/co/lettermint/types/RotateProjectTokenResponse.java | 2 +- src/main/java/co/lettermint/types/RouteData.java | 2 +- src/main/java/co/lettermint/types/RouteDataSettings.java | 2 +- src/main/java/co/lettermint/types/RouteListData.java | 2 +- src/main/java/co/lettermint/types/RouteMutationResponse.java | 2 +- src/main/java/co/lettermint/types/RouteStatisticData.java | 2 +- src/main/java/co/lettermint/types/RouteType.java | 2 +- src/main/java/co/lettermint/types/SandboxResult.java | 2 +- src/main/java/co/lettermint/types/ScheduledMessage.java | 2 +- .../java/co/lettermint/types/ScheduledSendMailResponse.java | 2 +- src/main/java/co/lettermint/types/SendMailRequest.java | 2 +- src/main/java/co/lettermint/types/SendMailRequestSettings.java | 2 +- src/main/java/co/lettermint/types/SendMailResponse.java | 2 +- src/main/java/co/lettermint/types/SpamSymbol.java | 2 +- src/main/java/co/lettermint/types/StatsDailyData.java | 2 +- src/main/java/co/lettermint/types/StatsData.java | 2 +- src/main/java/co/lettermint/types/StatsInboundData.java | 2 +- src/main/java/co/lettermint/types/StatsTotalsData.java | 2 +- src/main/java/co/lettermint/types/StatsTypeData.java | 2 +- src/main/java/co/lettermint/types/StoreDomainData.java | 2 +- src/main/java/co/lettermint/types/StoreProjectData.java | 2 +- src/main/java/co/lettermint/types/StoreRouteData.java | 2 +- src/main/java/co/lettermint/types/StoreSuppressionData.java | 2 +- src/main/java/co/lettermint/types/StoreWebhookData.java | 2 +- src/main/java/co/lettermint/types/SuppressedRecipientData.java | 2 +- src/main/java/co/lettermint/types/SuppressionAppliesTo.java | 2 +- src/main/java/co/lettermint/types/SuppressionCreateReason.java | 2 +- src/main/java/co/lettermint/types/SuppressionCreateScope.java | 2 +- .../java/co/lettermint/types/SuppressionDeletedResponse.java | 2 +- src/main/java/co/lettermint/types/SuppressionReason.java | 2 +- .../java/co/lettermint/types/SuppressionReviewResponse.java | 2 +- .../co/lettermint/types/SuppressionReviewResponseStatus.java | 2 +- src/main/java/co/lettermint/types/SuppressionScope.java | 2 +- .../java/co/lettermint/types/SuppressionSourceMessageData.java | 2 +- src/main/java/co/lettermint/types/SuppressionStoreResponse.java | 2 +- src/main/java/co/lettermint/types/SuppressionStoreResult.java | 2 +- src/main/java/co/lettermint/types/SuppressionType.java | 2 +- src/main/java/co/lettermint/types/TeamAddonData.java | 2 +- src/main/java/co/lettermint/types/TeamData.java | 2 +- src/main/java/co/lettermint/types/TeamMemberData.java | 2 +- src/main/java/co/lettermint/types/TeamMemberDataRole.java | 2 +- .../java/co/lettermint/types/TeamMemberProjectAccessData.java | 2 +- .../types/TeamMemberProjectAccessDataProjectsItem.java | 2 +- src/main/java/co/lettermint/types/TeamMutationResponse.java | 2 +- src/main/java/co/lettermint/types/TeamRoleData.java | 2 +- src/main/java/co/lettermint/types/TeamRoleListResponse.java | 2 +- src/main/java/co/lettermint/types/TeamType.java | 2 +- src/main/java/co/lettermint/types/TeamUsageDetailData.java | 2 +- src/main/java/co/lettermint/types/TeamUsagePeriodData.java | 2 +- src/main/java/co/lettermint/types/TestWebhookResponse.java | 2 +- src/main/java/co/lettermint/types/TlsPolicy.java | 2 +- src/main/java/co/lettermint/types/UpdateDomainProjectsData.java | 2 +- src/main/java/co/lettermint/types/UpdateProjectData.java | 2 +- .../co/lettermint/types/UpdateReportForwardingResponse.java | 2 +- src/main/java/co/lettermint/types/UpdateRouteData.java | 2 +- .../co/lettermint/types/UpdateRouteInboundSettingsData.java | 2 +- src/main/java/co/lettermint/types/UpdateRouteSettingsData.java | 2 +- src/main/java/co/lettermint/types/UpdateTeamData.java | 2 +- .../co/lettermint/types/UpdateTeamMemberAssignmentData.java | 2 +- .../types/UpdateTeamMemberAssignmentDataProjectAccess.java | 2 +- src/main/java/co/lettermint/types/UpdateWebhookData.java | 2 +- src/main/java/co/lettermint/types/ValidationError.java | 2 +- .../java/co/lettermint/types/VerifyReportForwardingRequest.java | 2 +- .../co/lettermint/types/VerifyReportForwardingResponse.java | 2 +- src/main/java/co/lettermint/types/WebhookBasicAuthData.java | 2 +- src/main/java/co/lettermint/types/WebhookData.java | 2 +- src/main/java/co/lettermint/types/WebhookDeliveryData.java | 2 +- src/main/java/co/lettermint/types/WebhookDeliveryListData.java | 2 +- .../java/co/lettermint/types/WebhookDeliveryModeFilter.java | 2 +- src/main/java/co/lettermint/types/WebhookDeliveryStatus.java | 2 +- src/main/java/co/lettermint/types/WebhookEvent.java | 2 +- src/main/java/co/lettermint/types/WebhookListData.java | 2 +- src/main/java/co/lettermint/types/WebhookMutationResponse.java | 2 +- src/main/java/co/lettermint/types/WebhookScope.java | 2 +- src/main/java/co/lettermint/types/WebhookSecretData.java | 2 +- src/main/java/co/lettermint/types/WebhookSecretResponse.java | 2 +- 203 files changed, 203 insertions(+), 203 deletions(-) diff --git a/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java b/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java index 24893c3..8654e7a 100644 --- a/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java +++ b/src/main/java/co/lettermint/types/AnalyticsBreakdownRow.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java b/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java index 7c5285b..cd0978e 100644 --- a/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java +++ b/src/main/java/co/lettermint/types/AnalyticsCatalogueDimension.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java b/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java index c690978..34c33aa 100644 --- a/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java +++ b/src/main/java/co/lettermint/types/AnalyticsCatalogueGroupDimension.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsComparison.java b/src/main/java/co/lettermint/types/AnalyticsComparison.java index 97f4da6..98f2e4d 100644 --- a/src/main/java/co/lettermint/types/AnalyticsComparison.java +++ b/src/main/java/co/lettermint/types/AnalyticsComparison.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java b/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java index 152f117..3ee8e7d 100644 --- a/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java +++ b/src/main/java/co/lettermint/types/AnalyticsComparisonValues.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsDimension.java b/src/main/java/co/lettermint/types/AnalyticsDimension.java index c13186d..59a2c96 100644 --- a/src/main/java/co/lettermint/types/AnalyticsDimension.java +++ b/src/main/java/co/lettermint/types/AnalyticsDimension.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsFilter.java b/src/main/java/co/lettermint/types/AnalyticsFilter.java index c0b4f8d..bc31118 100644 --- a/src/main/java/co/lettermint/types/AnalyticsFilter.java +++ b/src/main/java/co/lettermint/types/AnalyticsFilter.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java b/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java index f7abe1d..13079de 100644 --- a/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java +++ b/src/main/java/co/lettermint/types/AnalyticsFilterOperator.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java b/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java index 2179089..a907286 100644 --- a/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java +++ b/src/main/java/co/lettermint/types/AnalyticsGroupDimension.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsInterval.java b/src/main/java/co/lettermint/types/AnalyticsInterval.java index f0bd87e..2a48aa5 100644 --- a/src/main/java/co/lettermint/types/AnalyticsInterval.java +++ b/src/main/java/co/lettermint/types/AnalyticsInterval.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMeta.java b/src/main/java/co/lettermint/types/AnalyticsMeta.java index 8a6c883..55762ac 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMeta.java +++ b/src/main/java/co/lettermint/types/AnalyticsMeta.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java b/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java index 857464d..1310f12 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetaAlignment.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java b/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java index e781853..c489578 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetaCollectionCompleteness.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java b/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java index ed5fbe7..b8f6628 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetaComparison.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java b/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java index 802d1fc..b17b37f 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetaTimeBasis.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetric.java b/src/main/java/co/lettermint/types/AnalyticsMetric.java index f6ed902..e277166 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetric.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetric.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetricChange.java b/src/main/java/co/lettermint/types/AnalyticsMetricChange.java index c25153e..bddb382 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetricChange.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetricChange.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsMetricValues.java b/src/main/java/co/lettermint/types/AnalyticsMetricValues.java index 7f099b1..92321f3 100644 --- a/src/main/java/co/lettermint/types/AnalyticsMetricValues.java +++ b/src/main/java/co/lettermint/types/AnalyticsMetricValues.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsPagination.java b/src/main/java/co/lettermint/types/AnalyticsPagination.java index ca7911a..1e34e7b 100644 --- a/src/main/java/co/lettermint/types/AnalyticsPagination.java +++ b/src/main/java/co/lettermint/types/AnalyticsPagination.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsQuery.java b/src/main/java/co/lettermint/types/AnalyticsQuery.java index 9df9de1..2aadd33 100644 --- a/src/main/java/co/lettermint/types/AnalyticsQuery.java +++ b/src/main/java/co/lettermint/types/AnalyticsQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsRateBase.java b/src/main/java/co/lettermint/types/AnalyticsRateBase.java index 09e8e5b..a3dbc75 100644 --- a/src/main/java/co/lettermint/types/AnalyticsRateBase.java +++ b/src/main/java/co/lettermint/types/AnalyticsRateBase.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsRateBases.java b/src/main/java/co/lettermint/types/AnalyticsRateBases.java index 84ae42d..97c5572 100644 --- a/src/main/java/co/lettermint/types/AnalyticsRateBases.java +++ b/src/main/java/co/lettermint/types/AnalyticsRateBases.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsResponse.java b/src/main/java/co/lettermint/types/AnalyticsResponse.java index bf87962..345ba04 100644 --- a/src/main/java/co/lettermint/types/AnalyticsResponse.java +++ b/src/main/java/co/lettermint/types/AnalyticsResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsResults.java b/src/main/java/co/lettermint/types/AnalyticsResults.java index 130c3fd..e6d35cf 100644 --- a/src/main/java/co/lettermint/types/AnalyticsResults.java +++ b/src/main/java/co/lettermint/types/AnalyticsResults.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsSection.java b/src/main/java/co/lettermint/types/AnalyticsSection.java index c35b8e8..0730822 100644 --- a/src/main/java/co/lettermint/types/AnalyticsSection.java +++ b/src/main/java/co/lettermint/types/AnalyticsSection.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsSort.java b/src/main/java/co/lettermint/types/AnalyticsSort.java index f4231f0..84a6c84 100644 --- a/src/main/java/co/lettermint/types/AnalyticsSort.java +++ b/src/main/java/co/lettermint/types/AnalyticsSort.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsSortDirection.java b/src/main/java/co/lettermint/types/AnalyticsSortDirection.java index ed53107..02d86c8 100644 --- a/src/main/java/co/lettermint/types/AnalyticsSortDirection.java +++ b/src/main/java/co/lettermint/types/AnalyticsSortDirection.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsSummary.java b/src/main/java/co/lettermint/types/AnalyticsSummary.java index de7b030..a7c310e 100644 --- a/src/main/java/co/lettermint/types/AnalyticsSummary.java +++ b/src/main/java/co/lettermint/types/AnalyticsSummary.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java b/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java index 1673246..675d8d6 100644 --- a/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java +++ b/src/main/java/co/lettermint/types/AnalyticsTimeSeriesPoint.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ApiError.java b/src/main/java/co/lettermint/types/ApiError.java index d2656d0..c40fda2 100644 --- a/src/main/java/co/lettermint/types/ApiError.java +++ b/src/main/java/co/lettermint/types/ApiError.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ApiErrorDetail.java b/src/main/java/co/lettermint/types/ApiErrorDetail.java index 6bb3549..2050f7c 100644 --- a/src/main/java/co/lettermint/types/ApiErrorDetail.java +++ b/src/main/java/co/lettermint/types/ApiErrorDetail.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/AttachmentDelivery.java b/src/main/java/co/lettermint/types/AttachmentDelivery.java index 447e801..9418a78 100644 --- a/src/main/java/co/lettermint/types/AttachmentDelivery.java +++ b/src/main/java/co/lettermint/types/AttachmentDelivery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/BlockedFileTypes.java b/src/main/java/co/lettermint/types/BlockedFileTypes.java index 1f8459c..aac4600 100644 --- a/src/main/java/co/lettermint/types/BlockedFileTypes.java +++ b/src/main/java/co/lettermint/types/BlockedFileTypes.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/BuiltInTeamRole.java b/src/main/java/co/lettermint/types/BuiltInTeamRole.java index 42c18f6..a43a6a3 100644 --- a/src/main/java/co/lettermint/types/BuiltInTeamRole.java +++ b/src/main/java/co/lettermint/types/BuiltInTeamRole.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/Copies.java b/src/main/java/co/lettermint/types/Copies.java index 5a58041..c9e4e8b 100644 --- a/src/main/java/co/lettermint/types/Copies.java +++ b/src/main/java/co/lettermint/types/Copies.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/CursorPage.java b/src/main/java/co/lettermint/types/CursorPage.java index fb57279..5c300d6 100644 --- a/src/main/java/co/lettermint/types/CursorPage.java +++ b/src/main/java/co/lettermint/types/CursorPage.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java b/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java index 4bb774a..24be2d6 100644 --- a/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java +++ b/src/main/java/co/lettermint/types/DeleteSuppressionResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java b/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java index beb85b2..ab18196 100644 --- a/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java +++ b/src/main/java/co/lettermint/types/DeleteSuppressionResponseStatus.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DeliveryMode.java b/src/main/java/co/lettermint/types/DeliveryMode.java index ef8ab6e..09667c8 100644 --- a/src/main/java/co/lettermint/types/DeliveryMode.java +++ b/src/main/java/co/lettermint/types/DeliveryMode.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DkimMode.java b/src/main/java/co/lettermint/types/DkimMode.java index f4afe67..907ad42 100644 --- a/src/main/java/co/lettermint/types/DkimMode.java +++ b/src/main/java/co/lettermint/types/DkimMode.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DmarcPolicy.java b/src/main/java/co/lettermint/types/DmarcPolicy.java index 54f9fe6..9baf46e 100644 --- a/src/main/java/co/lettermint/types/DmarcPolicy.java +++ b/src/main/java/co/lettermint/types/DmarcPolicy.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsRecordPurpose.java b/src/main/java/co/lettermint/types/DnsRecordPurpose.java index 39cb0a7..c5356af 100644 --- a/src/main/java/co/lettermint/types/DnsRecordPurpose.java +++ b/src/main/java/co/lettermint/types/DnsRecordPurpose.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsRecordStatus.java b/src/main/java/co/lettermint/types/DnsRecordStatus.java index f01ff19..9238442 100644 --- a/src/main/java/co/lettermint/types/DnsRecordStatus.java +++ b/src/main/java/co/lettermint/types/DnsRecordStatus.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java b/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java index 1fb1aff..212ca79 100644 --- a/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java +++ b/src/main/java/co/lettermint/types/DnsRecordVerificationFailureResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationError.java b/src/main/java/co/lettermint/types/DnsVerificationError.java index b18ee2c..3e25635 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationError.java +++ b/src/main/java/co/lettermint/types/DnsVerificationError.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java b/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java index 71051b8..f7e3955 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java +++ b/src/main/java/co/lettermint/types/DnsVerificationFailedRecord.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java b/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java index 040fddb..bc3faa3 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java +++ b/src/main/java/co/lettermint/types/DnsVerificationFailureResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationResultData.java b/src/main/java/co/lettermint/types/DnsVerificationResultData.java index 10dc289..0de7fec 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationResultData.java +++ b/src/main/java/co/lettermint/types/DnsVerificationResultData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java b/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java index 267311f..d5be163 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java +++ b/src/main/java/co/lettermint/types/DnsVerificationResultDataDmarcSpfAlignmentIssue.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationScope.java b/src/main/java/co/lettermint/types/DnsVerificationScope.java index db81cd6..f5a95e8 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationScope.java +++ b/src/main/java/co/lettermint/types/DnsVerificationScope.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java b/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java index 15d6e77..c563891 100644 --- a/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java +++ b/src/main/java/co/lettermint/types/DnsVerificationSuccessResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DomainData.java b/src/main/java/co/lettermint/types/DomainData.java index 65a0482..a280d33 100644 --- a/src/main/java/co/lettermint/types/DomainData.java +++ b/src/main/java/co/lettermint/types/DomainData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DomainDataProjectsItem.java b/src/main/java/co/lettermint/types/DomainDataProjectsItem.java index 8156ddc..c395df3 100644 --- a/src/main/java/co/lettermint/types/DomainDataProjectsItem.java +++ b/src/main/java/co/lettermint/types/DomainDataProjectsItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DomainDnsRecordData.java b/src/main/java/co/lettermint/types/DomainDnsRecordData.java index ca79133..6b97123 100644 --- a/src/main/java/co/lettermint/types/DomainDnsRecordData.java +++ b/src/main/java/co/lettermint/types/DomainDnsRecordData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DomainListData.java b/src/main/java/co/lettermint/types/DomainListData.java index 0cb3434..c85093e 100644 --- a/src/main/java/co/lettermint/types/DomainListData.java +++ b/src/main/java/co/lettermint/types/DomainListData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DomainMutationResponse.java b/src/main/java/co/lettermint/types/DomainMutationResponse.java index 3159015..30ea0cc 100644 --- a/src/main/java/co/lettermint/types/DomainMutationResponse.java +++ b/src/main/java/co/lettermint/types/DomainMutationResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/DomainStatus.java b/src/main/java/co/lettermint/types/DomainStatus.java index 55835f7..255c4ee 100644 --- a/src/main/java/co/lettermint/types/DomainStatus.java +++ b/src/main/java/co/lettermint/types/DomainStatus.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ErrorMessage.java b/src/main/java/co/lettermint/types/ErrorMessage.java index 6e9e716..3cd3f2d 100644 --- a/src/main/java/co/lettermint/types/ErrorMessage.java +++ b/src/main/java/co/lettermint/types/ErrorMessage.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetDomainQuery.java b/src/main/java/co/lettermint/types/GetDomainQuery.java index b81e756..81669d7 100644 --- a/src/main/java/co/lettermint/types/GetDomainQuery.java +++ b/src/main/java/co/lettermint/types/GetDomainQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java index a2c9447..7634f0a 100644 --- a/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java +++ b/src/main/java/co/lettermint/types/GetDomainQueryIncludeItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetProjectQuery.java b/src/main/java/co/lettermint/types/GetProjectQuery.java index 7a3bba0..67e95fd 100644 --- a/src/main/java/co/lettermint/types/GetProjectQuery.java +++ b/src/main/java/co/lettermint/types/GetProjectQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java index 5634311..7fbbc64 100644 --- a/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java +++ b/src/main/java/co/lettermint/types/GetProjectQueryIncludeItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetReportForwardingResponse.java b/src/main/java/co/lettermint/types/GetReportForwardingResponse.java index e946ee1..0d1cecd 100644 --- a/src/main/java/co/lettermint/types/GetReportForwardingResponse.java +++ b/src/main/java/co/lettermint/types/GetReportForwardingResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetRouteQuery.java b/src/main/java/co/lettermint/types/GetRouteQuery.java index bf31315..537b1f9 100644 --- a/src/main/java/co/lettermint/types/GetRouteQuery.java +++ b/src/main/java/co/lettermint/types/GetRouteQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java index 4d186fa..21b8a84 100644 --- a/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java +++ b/src/main/java/co/lettermint/types/GetRouteQueryIncludeItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetStatsQuery.java b/src/main/java/co/lettermint/types/GetStatsQuery.java index c3d3edc..adbe7c4 100644 --- a/src/main/java/co/lettermint/types/GetStatsQuery.java +++ b/src/main/java/co/lettermint/types/GetStatsQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetTeamQuery.java b/src/main/java/co/lettermint/types/GetTeamQuery.java index 89cd848..56c7a13 100644 --- a/src/main/java/co/lettermint/types/GetTeamQuery.java +++ b/src/main/java/co/lettermint/types/GetTeamQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java b/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java index 1a8c902..2b7d682 100644 --- a/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java +++ b/src/main/java/co/lettermint/types/GetTeamQueryIncludeItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/InboundDomainVerification.java b/src/main/java/co/lettermint/types/InboundDomainVerification.java index 552d68b..5851017 100644 --- a/src/main/java/co/lettermint/types/InboundDomainVerification.java +++ b/src/main/java/co/lettermint/types/InboundDomainVerification.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java b/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java index 8690a14..3c85fee 100644 --- a/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java +++ b/src/main/java/co/lettermint/types/InboundDomainVerificationResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/InitialRoutes.java b/src/main/java/co/lettermint/types/InitialRoutes.java index b6610ae..baa5b56 100644 --- a/src/main/java/co/lettermint/types/InitialRoutes.java +++ b/src/main/java/co/lettermint/types/InitialRoutes.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListDomainsQuery.java b/src/main/java/co/lettermint/types/ListDomainsQuery.java index 597689f..8e3a47c 100644 --- a/src/main/java/co/lettermint/types/ListDomainsQuery.java +++ b/src/main/java/co/lettermint/types/ListDomainsQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java b/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java index cc6cf6f..2b71415 100644 --- a/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListDomainsQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListMessageEventsQuery.java b/src/main/java/co/lettermint/types/ListMessageEventsQuery.java index 1907b97..a5cafb4 100644 --- a/src/main/java/co/lettermint/types/ListMessageEventsQuery.java +++ b/src/main/java/co/lettermint/types/ListMessageEventsQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java b/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java index 58da925..e1bc2f5 100644 --- a/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListMessageEventsQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListMessagesQuery.java b/src/main/java/co/lettermint/types/ListMessagesQuery.java index d25639c..b6b4413 100644 --- a/src/main/java/co/lettermint/types/ListMessagesQuery.java +++ b/src/main/java/co/lettermint/types/ListMessagesQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java b/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java index 6a2b284..d7f9a92 100644 --- a/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java +++ b/src/main/java/co/lettermint/types/ListMessagesQueryFilter.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java b/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java index e61232a..5aead8b 100644 --- a/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java +++ b/src/main/java/co/lettermint/types/ListMessagesQueryFilterTagsItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java b/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java index d6bb534..84342ff 100644 --- a/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListMessagesQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListProjectsQuery.java b/src/main/java/co/lettermint/types/ListProjectsQuery.java index 23817a5..7528462 100644 --- a/src/main/java/co/lettermint/types/ListProjectsQuery.java +++ b/src/main/java/co/lettermint/types/ListProjectsQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java b/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java index 32cd815..dcffd9a 100644 --- a/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListProjectsQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListRoutesQuery.java b/src/main/java/co/lettermint/types/ListRoutesQuery.java index 25fb890..306fff5 100644 --- a/src/main/java/co/lettermint/types/ListRoutesQuery.java +++ b/src/main/java/co/lettermint/types/ListRoutesQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java b/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java index 7f4184b..cc1cc21 100644 --- a/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListRoutesQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListSuppressionsQuery.java b/src/main/java/co/lettermint/types/ListSuppressionsQuery.java index 34d0baf..bace833 100644 --- a/src/main/java/co/lettermint/types/ListSuppressionsQuery.java +++ b/src/main/java/co/lettermint/types/ListSuppressionsQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java b/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java index 1d143c0..30a0f0a 100644 --- a/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListSuppressionsQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListTeamMembersQuery.java b/src/main/java/co/lettermint/types/ListTeamMembersQuery.java index cd118ee..bff90a5 100644 --- a/src/main/java/co/lettermint/types/ListTeamMembersQuery.java +++ b/src/main/java/co/lettermint/types/ListTeamMembersQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java index 22ab70d..92b115f 100644 --- a/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java +++ b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java index 89b251e..87d3f5b 100644 --- a/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListWebhookDeliveriesQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListWebhooksQuery.java b/src/main/java/co/lettermint/types/ListWebhooksQuery.java index 7e17ad7..c95dd70 100644 --- a/src/main/java/co/lettermint/types/ListWebhooksQuery.java +++ b/src/main/java/co/lettermint/types/ListWebhooksQuery.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java b/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java index dc10c1e..4e83c07 100644 --- a/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java +++ b/src/main/java/co/lettermint/types/ListWebhooksQuerySortItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageAttachmentData.java b/src/main/java/co/lettermint/types/MessageAttachmentData.java index a1bb0c2..b2fe5fd 100644 --- a/src/main/java/co/lettermint/types/MessageAttachmentData.java +++ b/src/main/java/co/lettermint/types/MessageAttachmentData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageAttachmentInput.java b/src/main/java/co/lettermint/types/MessageAttachmentInput.java index ded5f3e..85d39ec 100644 --- a/src/main/java/co/lettermint/types/MessageAttachmentInput.java +++ b/src/main/java/co/lettermint/types/MessageAttachmentInput.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageData.java b/src/main/java/co/lettermint/types/MessageData.java index b920385..f6efed8 100644 --- a/src/main/java/co/lettermint/types/MessageData.java +++ b/src/main/java/co/lettermint/types/MessageData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageEventData.java b/src/main/java/co/lettermint/types/MessageEventData.java index 5e61876..3a862e8 100644 --- a/src/main/java/co/lettermint/types/MessageEventData.java +++ b/src/main/java/co/lettermint/types/MessageEventData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageEventType.java b/src/main/java/co/lettermint/types/MessageEventType.java index c2a7750..50203e5 100644 --- a/src/main/java/co/lettermint/types/MessageEventType.java +++ b/src/main/java/co/lettermint/types/MessageEventType.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageListData.java b/src/main/java/co/lettermint/types/MessageListData.java index 0478fe9..3548d38 100644 --- a/src/main/java/co/lettermint/types/MessageListData.java +++ b/src/main/java/co/lettermint/types/MessageListData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageRecipientData.java b/src/main/java/co/lettermint/types/MessageRecipientData.java index dd090bb..2e2117c 100644 --- a/src/main/java/co/lettermint/types/MessageRecipientData.java +++ b/src/main/java/co/lettermint/types/MessageRecipientData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageResponse.java b/src/main/java/co/lettermint/types/MessageResponse.java index 817fa4a..96cfefd 100644 --- a/src/main/java/co/lettermint/types/MessageResponse.java +++ b/src/main/java/co/lettermint/types/MessageResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageStatsData.java b/src/main/java/co/lettermint/types/MessageStatsData.java index e12ffea..6071cf9 100644 --- a/src/main/java/co/lettermint/types/MessageStatsData.java +++ b/src/main/java/co/lettermint/types/MessageStatsData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageStatus.java b/src/main/java/co/lettermint/types/MessageStatus.java index a907a80..9ff635a 100644 --- a/src/main/java/co/lettermint/types/MessageStatus.java +++ b/src/main/java/co/lettermint/types/MessageStatus.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageTag.java b/src/main/java/co/lettermint/types/MessageTag.java index 56c840b..3e012a0 100644 --- a/src/main/java/co/lettermint/types/MessageTag.java +++ b/src/main/java/co/lettermint/types/MessageTag.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageTagInput.java b/src/main/java/co/lettermint/types/MessageTagInput.java index 1375430..19452f4 100644 --- a/src/main/java/co/lettermint/types/MessageTagInput.java +++ b/src/main/java/co/lettermint/types/MessageTagInput.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/MessageType.java b/src/main/java/co/lettermint/types/MessageType.java index c93f195..987770b 100644 --- a/src/main/java/co/lettermint/types/MessageType.java +++ b/src/main/java/co/lettermint/types/MessageType.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/Operations.java b/src/main/java/co/lettermint/types/Operations.java index a3f5625..10c465f 100644 --- a/src/main/java/co/lettermint/types/Operations.java +++ b/src/main/java/co/lettermint/types/Operations.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/OptionalNullable.java b/src/main/java/co/lettermint/types/OptionalNullable.java index 4244fb9..146aedf 100644 --- a/src/main/java/co/lettermint/types/OptionalNullable.java +++ b/src/main/java/co/lettermint/types/OptionalNullable.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/PendingSendMailResponse.java b/src/main/java/co/lettermint/types/PendingSendMailResponse.java index 5a48653..de59ccc 100644 --- a/src/main/java/co/lettermint/types/PendingSendMailResponse.java +++ b/src/main/java/co/lettermint/types/PendingSendMailResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/Plan.java b/src/main/java/co/lettermint/types/Plan.java index 943a0a9..73d2661 100644 --- a/src/main/java/co/lettermint/types/Plan.java +++ b/src/main/java/co/lettermint/types/Plan.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java b/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java index efcb02d..27f0644 100644 --- a/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageConflict.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java index fa0ca7e..e68a5f0 100644 --- a/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictError.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java index c5d47e8..c1495b8 100644 --- a/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageConflictErrorCode.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java b/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java index 144ca14..928924e 100644 --- a/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java b/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java index cc26ee7..ff27ad8 100644 --- a/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java +++ b/src/main/java/co/lettermint/types/ProcessInboundMessageResult.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProjectAccessScope.java b/src/main/java/co/lettermint/types/ProjectAccessScope.java index 439ed7e..6ddda29 100644 --- a/src/main/java/co/lettermint/types/ProjectAccessScope.java +++ b/src/main/java/co/lettermint/types/ProjectAccessScope.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProjectCreatedData.java b/src/main/java/co/lettermint/types/ProjectCreatedData.java index 04af7c0..e2efa62 100644 --- a/src/main/java/co/lettermint/types/ProjectCreatedData.java +++ b/src/main/java/co/lettermint/types/ProjectCreatedData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProjectData.java b/src/main/java/co/lettermint/types/ProjectData.java index ec93402..123782a 100644 --- a/src/main/java/co/lettermint/types/ProjectData.java +++ b/src/main/java/co/lettermint/types/ProjectData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProjectListData.java b/src/main/java/co/lettermint/types/ProjectListData.java index 0909c11..be7e646 100644 --- a/src/main/java/co/lettermint/types/ProjectListData.java +++ b/src/main/java/co/lettermint/types/ProjectListData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ProjectMutationResponse.java b/src/main/java/co/lettermint/types/ProjectMutationResponse.java index 621acc0..76f8319 100644 --- a/src/main/java/co/lettermint/types/ProjectMutationResponse.java +++ b/src/main/java/co/lettermint/types/ProjectMutationResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/QueryParameters.java b/src/main/java/co/lettermint/types/QueryParameters.java index adfb1b3..ee38344 100644 --- a/src/main/java/co/lettermint/types/QueryParameters.java +++ b/src/main/java/co/lettermint/types/QueryParameters.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RbacConflictCode.java b/src/main/java/co/lettermint/types/RbacConflictCode.java index a9cf987..60af4da 100644 --- a/src/main/java/co/lettermint/types/RbacConflictCode.java +++ b/src/main/java/co/lettermint/types/RbacConflictCode.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RbacConflictException.java b/src/main/java/co/lettermint/types/RbacConflictException.java index d63d060..6311141 100644 --- a/src/main/java/co/lettermint/types/RbacConflictException.java +++ b/src/main/java/co/lettermint/types/RbacConflictException.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RbacConflictExceptionError.java b/src/main/java/co/lettermint/types/RbacConflictExceptionError.java index d6ae5d9..f1eaa7b 100644 --- a/src/main/java/co/lettermint/types/RbacConflictExceptionError.java +++ b/src/main/java/co/lettermint/types/RbacConflictExceptionError.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RbacPermission.java b/src/main/java/co/lettermint/types/RbacPermission.java index b956a78..6e50218 100644 --- a/src/main/java/co/lettermint/types/RbacPermission.java +++ b/src/main/java/co/lettermint/types/RbacPermission.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RecordType.java b/src/main/java/co/lettermint/types/RecordType.java index cf6e3ab..f5e8107 100644 --- a/src/main/java/co/lettermint/types/RecordType.java +++ b/src/main/java/co/lettermint/types/RecordType.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ReportForwardingRequest.java b/src/main/java/co/lettermint/types/ReportForwardingRequest.java index 7d38d17..afb464d 100644 --- a/src/main/java/co/lettermint/types/ReportForwardingRequest.java +++ b/src/main/java/co/lettermint/types/ReportForwardingRequest.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ReportForwardingResource.java b/src/main/java/co/lettermint/types/ReportForwardingResource.java index c2c8480..7622de5 100644 --- a/src/main/java/co/lettermint/types/ReportForwardingResource.java +++ b/src/main/java/co/lettermint/types/ReportForwardingResource.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RescheduleMessageRequest.java b/src/main/java/co/lettermint/types/RescheduleMessageRequest.java index 2e7ff92..d70c6e1 100644 --- a/src/main/java/co/lettermint/types/RescheduleMessageRequest.java +++ b/src/main/java/co/lettermint/types/RescheduleMessageRequest.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java b/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java index b6d7ee0..82f428d 100644 --- a/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java +++ b/src/main/java/co/lettermint/types/ResendReportForwardingCodeResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java b/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java index 1bf6e8e..7a95fc0 100644 --- a/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java +++ b/src/main/java/co/lettermint/types/RotateProjectTokenResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RouteData.java b/src/main/java/co/lettermint/types/RouteData.java index 4ad4445..848a254 100644 --- a/src/main/java/co/lettermint/types/RouteData.java +++ b/src/main/java/co/lettermint/types/RouteData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RouteDataSettings.java b/src/main/java/co/lettermint/types/RouteDataSettings.java index c96dc1e..4584c58 100644 --- a/src/main/java/co/lettermint/types/RouteDataSettings.java +++ b/src/main/java/co/lettermint/types/RouteDataSettings.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RouteListData.java b/src/main/java/co/lettermint/types/RouteListData.java index e291f0d..db1e588 100644 --- a/src/main/java/co/lettermint/types/RouteListData.java +++ b/src/main/java/co/lettermint/types/RouteListData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RouteMutationResponse.java b/src/main/java/co/lettermint/types/RouteMutationResponse.java index aa2a5ec..02720b8 100644 --- a/src/main/java/co/lettermint/types/RouteMutationResponse.java +++ b/src/main/java/co/lettermint/types/RouteMutationResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RouteStatisticData.java b/src/main/java/co/lettermint/types/RouteStatisticData.java index 050b976..9b157ad 100644 --- a/src/main/java/co/lettermint/types/RouteStatisticData.java +++ b/src/main/java/co/lettermint/types/RouteStatisticData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/RouteType.java b/src/main/java/co/lettermint/types/RouteType.java index acc2c66..c5abeb3 100644 --- a/src/main/java/co/lettermint/types/RouteType.java +++ b/src/main/java/co/lettermint/types/RouteType.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SandboxResult.java b/src/main/java/co/lettermint/types/SandboxResult.java index 8ad9621..f97e85e 100644 --- a/src/main/java/co/lettermint/types/SandboxResult.java +++ b/src/main/java/co/lettermint/types/SandboxResult.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ScheduledMessage.java b/src/main/java/co/lettermint/types/ScheduledMessage.java index 3d5beb2..348fcce 100644 --- a/src/main/java/co/lettermint/types/ScheduledMessage.java +++ b/src/main/java/co/lettermint/types/ScheduledMessage.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java b/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java index beb9c28..ef86267 100644 --- a/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java +++ b/src/main/java/co/lettermint/types/ScheduledSendMailResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SendMailRequest.java b/src/main/java/co/lettermint/types/SendMailRequest.java index 952bb97..fba7019 100644 --- a/src/main/java/co/lettermint/types/SendMailRequest.java +++ b/src/main/java/co/lettermint/types/SendMailRequest.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SendMailRequestSettings.java b/src/main/java/co/lettermint/types/SendMailRequestSettings.java index 1750216..44db530 100644 --- a/src/main/java/co/lettermint/types/SendMailRequestSettings.java +++ b/src/main/java/co/lettermint/types/SendMailRequestSettings.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SendMailResponse.java b/src/main/java/co/lettermint/types/SendMailResponse.java index 3b2c0fd..ea4d591 100644 --- a/src/main/java/co/lettermint/types/SendMailResponse.java +++ b/src/main/java/co/lettermint/types/SendMailResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SpamSymbol.java b/src/main/java/co/lettermint/types/SpamSymbol.java index 9dc73b9..cae868e 100644 --- a/src/main/java/co/lettermint/types/SpamSymbol.java +++ b/src/main/java/co/lettermint/types/SpamSymbol.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StatsDailyData.java b/src/main/java/co/lettermint/types/StatsDailyData.java index fcebf6c..39866b5 100644 --- a/src/main/java/co/lettermint/types/StatsDailyData.java +++ b/src/main/java/co/lettermint/types/StatsDailyData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StatsData.java b/src/main/java/co/lettermint/types/StatsData.java index 63d0a2b..3a06b74 100644 --- a/src/main/java/co/lettermint/types/StatsData.java +++ b/src/main/java/co/lettermint/types/StatsData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StatsInboundData.java b/src/main/java/co/lettermint/types/StatsInboundData.java index 6d701b1..f2dde0c 100644 --- a/src/main/java/co/lettermint/types/StatsInboundData.java +++ b/src/main/java/co/lettermint/types/StatsInboundData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StatsTotalsData.java b/src/main/java/co/lettermint/types/StatsTotalsData.java index efe625a..a15a403 100644 --- a/src/main/java/co/lettermint/types/StatsTotalsData.java +++ b/src/main/java/co/lettermint/types/StatsTotalsData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StatsTypeData.java b/src/main/java/co/lettermint/types/StatsTypeData.java index d347f88..68767aa 100644 --- a/src/main/java/co/lettermint/types/StatsTypeData.java +++ b/src/main/java/co/lettermint/types/StatsTypeData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StoreDomainData.java b/src/main/java/co/lettermint/types/StoreDomainData.java index 955aa38..c9beedf 100644 --- a/src/main/java/co/lettermint/types/StoreDomainData.java +++ b/src/main/java/co/lettermint/types/StoreDomainData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StoreProjectData.java b/src/main/java/co/lettermint/types/StoreProjectData.java index 029108b..9083c78 100644 --- a/src/main/java/co/lettermint/types/StoreProjectData.java +++ b/src/main/java/co/lettermint/types/StoreProjectData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StoreRouteData.java b/src/main/java/co/lettermint/types/StoreRouteData.java index a4bd8ff..9ca584e 100644 --- a/src/main/java/co/lettermint/types/StoreRouteData.java +++ b/src/main/java/co/lettermint/types/StoreRouteData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StoreSuppressionData.java b/src/main/java/co/lettermint/types/StoreSuppressionData.java index 19c829b..be8ef1e 100644 --- a/src/main/java/co/lettermint/types/StoreSuppressionData.java +++ b/src/main/java/co/lettermint/types/StoreSuppressionData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/StoreWebhookData.java b/src/main/java/co/lettermint/types/StoreWebhookData.java index 9493489..3dd9dac 100644 --- a/src/main/java/co/lettermint/types/StoreWebhookData.java +++ b/src/main/java/co/lettermint/types/StoreWebhookData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressedRecipientData.java b/src/main/java/co/lettermint/types/SuppressedRecipientData.java index ec856e9..590f532 100644 --- a/src/main/java/co/lettermint/types/SuppressedRecipientData.java +++ b/src/main/java/co/lettermint/types/SuppressedRecipientData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionAppliesTo.java b/src/main/java/co/lettermint/types/SuppressionAppliesTo.java index 4a2109b..dab80a0 100644 --- a/src/main/java/co/lettermint/types/SuppressionAppliesTo.java +++ b/src/main/java/co/lettermint/types/SuppressionAppliesTo.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionCreateReason.java b/src/main/java/co/lettermint/types/SuppressionCreateReason.java index c9c2b40..a6642ac 100644 --- a/src/main/java/co/lettermint/types/SuppressionCreateReason.java +++ b/src/main/java/co/lettermint/types/SuppressionCreateReason.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionCreateScope.java b/src/main/java/co/lettermint/types/SuppressionCreateScope.java index 453084b..4c10798 100644 --- a/src/main/java/co/lettermint/types/SuppressionCreateScope.java +++ b/src/main/java/co/lettermint/types/SuppressionCreateScope.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java b/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java index b876a36..a089f07 100644 --- a/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java +++ b/src/main/java/co/lettermint/types/SuppressionDeletedResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionReason.java b/src/main/java/co/lettermint/types/SuppressionReason.java index 92fbd42..9df00f4 100644 --- a/src/main/java/co/lettermint/types/SuppressionReason.java +++ b/src/main/java/co/lettermint/types/SuppressionReason.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionReviewResponse.java b/src/main/java/co/lettermint/types/SuppressionReviewResponse.java index 9351fc3..45ba6ce 100644 --- a/src/main/java/co/lettermint/types/SuppressionReviewResponse.java +++ b/src/main/java/co/lettermint/types/SuppressionReviewResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java b/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java index 3c4b1bf..6d72867 100644 --- a/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java +++ b/src/main/java/co/lettermint/types/SuppressionReviewResponseStatus.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionScope.java b/src/main/java/co/lettermint/types/SuppressionScope.java index 609dcaa..8e50857 100644 --- a/src/main/java/co/lettermint/types/SuppressionScope.java +++ b/src/main/java/co/lettermint/types/SuppressionScope.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java b/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java index 63786f8..58d42ad 100644 --- a/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java +++ b/src/main/java/co/lettermint/types/SuppressionSourceMessageData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionStoreResponse.java b/src/main/java/co/lettermint/types/SuppressionStoreResponse.java index 8b87825..ec89dc7 100644 --- a/src/main/java/co/lettermint/types/SuppressionStoreResponse.java +++ b/src/main/java/co/lettermint/types/SuppressionStoreResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionStoreResult.java b/src/main/java/co/lettermint/types/SuppressionStoreResult.java index 4ff7fae..148a511 100644 --- a/src/main/java/co/lettermint/types/SuppressionStoreResult.java +++ b/src/main/java/co/lettermint/types/SuppressionStoreResult.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/SuppressionType.java b/src/main/java/co/lettermint/types/SuppressionType.java index a82c349..12154ae 100644 --- a/src/main/java/co/lettermint/types/SuppressionType.java +++ b/src/main/java/co/lettermint/types/SuppressionType.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamAddonData.java b/src/main/java/co/lettermint/types/TeamAddonData.java index d4c1191..bfa502f 100644 --- a/src/main/java/co/lettermint/types/TeamAddonData.java +++ b/src/main/java/co/lettermint/types/TeamAddonData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamData.java b/src/main/java/co/lettermint/types/TeamData.java index e3a2e8c..e982679 100644 --- a/src/main/java/co/lettermint/types/TeamData.java +++ b/src/main/java/co/lettermint/types/TeamData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamMemberData.java b/src/main/java/co/lettermint/types/TeamMemberData.java index 073072d..b30478f 100644 --- a/src/main/java/co/lettermint/types/TeamMemberData.java +++ b/src/main/java/co/lettermint/types/TeamMemberData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamMemberDataRole.java b/src/main/java/co/lettermint/types/TeamMemberDataRole.java index db971bc..4966178 100644 --- a/src/main/java/co/lettermint/types/TeamMemberDataRole.java +++ b/src/main/java/co/lettermint/types/TeamMemberDataRole.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java b/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java index e20603c..9cd29d9 100644 --- a/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java +++ b/src/main/java/co/lettermint/types/TeamMemberProjectAccessData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java b/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java index fdf6994..8020051 100644 --- a/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java +++ b/src/main/java/co/lettermint/types/TeamMemberProjectAccessDataProjectsItem.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamMutationResponse.java b/src/main/java/co/lettermint/types/TeamMutationResponse.java index 21b7051..2635b64 100644 --- a/src/main/java/co/lettermint/types/TeamMutationResponse.java +++ b/src/main/java/co/lettermint/types/TeamMutationResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamRoleData.java b/src/main/java/co/lettermint/types/TeamRoleData.java index 087500b..bf64571 100644 --- a/src/main/java/co/lettermint/types/TeamRoleData.java +++ b/src/main/java/co/lettermint/types/TeamRoleData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamRoleListResponse.java b/src/main/java/co/lettermint/types/TeamRoleListResponse.java index e131bf8..4e8c5f7 100644 --- a/src/main/java/co/lettermint/types/TeamRoleListResponse.java +++ b/src/main/java/co/lettermint/types/TeamRoleListResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamType.java b/src/main/java/co/lettermint/types/TeamType.java index deec81c..bbb45ee 100644 --- a/src/main/java/co/lettermint/types/TeamType.java +++ b/src/main/java/co/lettermint/types/TeamType.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamUsageDetailData.java b/src/main/java/co/lettermint/types/TeamUsageDetailData.java index 3b0fcf9..fc5176a 100644 --- a/src/main/java/co/lettermint/types/TeamUsageDetailData.java +++ b/src/main/java/co/lettermint/types/TeamUsageDetailData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TeamUsagePeriodData.java b/src/main/java/co/lettermint/types/TeamUsagePeriodData.java index a903edb..501b3ba 100644 --- a/src/main/java/co/lettermint/types/TeamUsagePeriodData.java +++ b/src/main/java/co/lettermint/types/TeamUsagePeriodData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TestWebhookResponse.java b/src/main/java/co/lettermint/types/TestWebhookResponse.java index 0410529..0958c73 100644 --- a/src/main/java/co/lettermint/types/TestWebhookResponse.java +++ b/src/main/java/co/lettermint/types/TestWebhookResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/TlsPolicy.java b/src/main/java/co/lettermint/types/TlsPolicy.java index 94be5af..994a757 100644 --- a/src/main/java/co/lettermint/types/TlsPolicy.java +++ b/src/main/java/co/lettermint/types/TlsPolicy.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java b/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java index 93a163c..8db4c10 100644 --- a/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java +++ b/src/main/java/co/lettermint/types/UpdateDomainProjectsData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateProjectData.java b/src/main/java/co/lettermint/types/UpdateProjectData.java index 351b2a0..dad10bc 100644 --- a/src/main/java/co/lettermint/types/UpdateProjectData.java +++ b/src/main/java/co/lettermint/types/UpdateProjectData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java b/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java index eb03d33..d406419 100644 --- a/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java +++ b/src/main/java/co/lettermint/types/UpdateReportForwardingResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateRouteData.java b/src/main/java/co/lettermint/types/UpdateRouteData.java index a6c5633..2db318e 100644 --- a/src/main/java/co/lettermint/types/UpdateRouteData.java +++ b/src/main/java/co/lettermint/types/UpdateRouteData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java b/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java index dc4a225..55139d6 100644 --- a/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java +++ b/src/main/java/co/lettermint/types/UpdateRouteInboundSettingsData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java b/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java index 6cad7e7..be64683 100644 --- a/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java +++ b/src/main/java/co/lettermint/types/UpdateRouteSettingsData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateTeamData.java b/src/main/java/co/lettermint/types/UpdateTeamData.java index a8a67f4..55caca9 100644 --- a/src/main/java/co/lettermint/types/UpdateTeamData.java +++ b/src/main/java/co/lettermint/types/UpdateTeamData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java index 3260355..e8ffdfb 100644 --- a/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java +++ b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java index 7b6a153..dcfff93 100644 --- a/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java +++ b/src/main/java/co/lettermint/types/UpdateTeamMemberAssignmentDataProjectAccess.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/UpdateWebhookData.java b/src/main/java/co/lettermint/types/UpdateWebhookData.java index f1723fa..39038e7 100644 --- a/src/main/java/co/lettermint/types/UpdateWebhookData.java +++ b/src/main/java/co/lettermint/types/UpdateWebhookData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/ValidationError.java b/src/main/java/co/lettermint/types/ValidationError.java index fcf7a41..1b8550b 100644 --- a/src/main/java/co/lettermint/types/ValidationError.java +++ b/src/main/java/co/lettermint/types/ValidationError.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java b/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java index 31707f1..f1a8196 100644 --- a/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java +++ b/src/main/java/co/lettermint/types/VerifyReportForwardingRequest.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java b/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java index 5c34e3b..059d4a6 100644 --- a/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java +++ b/src/main/java/co/lettermint/types/VerifyReportForwardingResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookBasicAuthData.java b/src/main/java/co/lettermint/types/WebhookBasicAuthData.java index 917e9aa..b61e0e3 100644 --- a/src/main/java/co/lettermint/types/WebhookBasicAuthData.java +++ b/src/main/java/co/lettermint/types/WebhookBasicAuthData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookData.java b/src/main/java/co/lettermint/types/WebhookData.java index 213cdb9..beba7d0 100644 --- a/src/main/java/co/lettermint/types/WebhookData.java +++ b/src/main/java/co/lettermint/types/WebhookData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryData.java b/src/main/java/co/lettermint/types/WebhookDeliveryData.java index 537a405..5e067ed 100644 --- a/src/main/java/co/lettermint/types/WebhookDeliveryData.java +++ b/src/main/java/co/lettermint/types/WebhookDeliveryData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryListData.java b/src/main/java/co/lettermint/types/WebhookDeliveryListData.java index 30a44f8..10f9470 100644 --- a/src/main/java/co/lettermint/types/WebhookDeliveryListData.java +++ b/src/main/java/co/lettermint/types/WebhookDeliveryListData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java b/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java index 3499403..262f34e 100644 --- a/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java +++ b/src/main/java/co/lettermint/types/WebhookDeliveryModeFilter.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java b/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java index 7697c3a..45a13a5 100644 --- a/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java +++ b/src/main/java/co/lettermint/types/WebhookDeliveryStatus.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookEvent.java b/src/main/java/co/lettermint/types/WebhookEvent.java index 132af04..336dcb9 100644 --- a/src/main/java/co/lettermint/types/WebhookEvent.java +++ b/src/main/java/co/lettermint/types/WebhookEvent.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookListData.java b/src/main/java/co/lettermint/types/WebhookListData.java index 9449cf5..a55be7d 100644 --- a/src/main/java/co/lettermint/types/WebhookListData.java +++ b/src/main/java/co/lettermint/types/WebhookListData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookMutationResponse.java b/src/main/java/co/lettermint/types/WebhookMutationResponse.java index e110dce..14db2e1 100644 --- a/src/main/java/co/lettermint/types/WebhookMutationResponse.java +++ b/src/main/java/co/lettermint/types/WebhookMutationResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookScope.java b/src/main/java/co/lettermint/types/WebhookScope.java index 2767a8f..9b45905 100644 --- a/src/main/java/co/lettermint/types/WebhookScope.java +++ b/src/main/java/co/lettermint/types/WebhookScope.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookSecretData.java b/src/main/java/co/lettermint/types/WebhookSecretData.java index 623253a..f98ca85 100644 --- a/src/main/java/co/lettermint/types/WebhookSecretData.java +++ b/src/main/java/co/lettermint/types/WebhookSecretData.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next diff --git a/src/main/java/co/lettermint/types/WebhookSecretResponse.java b/src/main/java/co/lettermint/types/WebhookSecretResponse.java index b1162ad..ebaccd0 100644 --- a/src/main/java/co/lettermint/types/WebhookSecretResponse.java +++ b/src/main/java/co/lettermint/types/WebhookSecretResponse.java @@ -1,5 +1,5 @@ // Generated by lettermint/sdk-generator — do not edit. -// Spec: lettermint/lettermint@80d8ab2a2d73644c2bdee8a4bb9d3565aa017d72 (feat/openapi-named-schemas) +// Spec: lettermint/lettermint@0b4ecbdd237d155305b9aab19efe96b2a4830446 (main) // sending-openapi.json SHA-256: 53e80a6c21cd8995a02c75dfbef79773242cd0d60a5e6262eb79dc127f779c7f // team-openapi.json SHA-256: 8b379814a0f501d2c564858bc382a29133535e704cc279545a934db611d587dd // Naming profile: next