@primitivedotdev/sdk 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -103,6 +103,28 @@ await client.reply(email, {
103
103
  });
104
104
  ```
105
105
 
106
+ ### HTML replies and waiting on the delivery outcome
107
+
108
+ `reply()` accepts `html` as a sibling of `text`, plus the same `wait` flag the
109
+ top-level `send()` takes:
110
+
111
+ ```ts
112
+ await client.reply(email, {
113
+ text: "Thanks for your email.",
114
+ html: "<p>Thanks for your email.</p>",
115
+ wait: true,
116
+ });
117
+ ```
118
+
119
+ `subject` is intentionally not accepted on `reply()`. Gmail's Conversation View
120
+ needs both a References match and a normalized-subject match to thread, so a
121
+ custom subject silently breaks the thread for half the recipient population.
122
+ Use `client.send(...)` if you need full subject control.
123
+
124
+ If the inbound row is not in a state we can reply to (no `Message-Id` recorded,
125
+ or content was discarded), the API returns `inbound_not_repliable` (HTTP 422)
126
+ and the SDK throws.
127
+
106
128
  ### Forward an inbound email
107
129
 
108
130
  ```ts
@@ -1,2 +1,2 @@
1
1
  // This file is auto-generated by @hey-api/openapi-ts
2
- export { addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, replayDelivery, replayEmailWebhooks, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain } from './sdk.gen.js';
2
+ export { addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain } from './sdk.gen.js';
@@ -184,6 +184,32 @@ export const downloadAttachments = (options) => (options.client ?? client).get({
184
184
  url: '/emails/{id}/attachments.tar.gz',
185
185
  ...options
186
186
  });
187
+ /**
188
+ * Reply to an inbound email
189
+ *
190
+ * Sends an outbound reply to the inbound email identified by `id`.
191
+ * Threading headers (`In-Reply-To`, `References`), recipient
192
+ * derivation (Reply-To, then From, then bare sender), and the
193
+ * `Re:` subject prefix are all derived server-side from the
194
+ * stored inbound row. The request body carries only the message
195
+ * body and optional `wait` flag; passing any header or recipient
196
+ * override is rejected by the schema (`additionalProperties:
197
+ * false`).
198
+ *
199
+ * Forwards through the same gates as `/send-mail`: the response
200
+ * status, error envelope, and `idempotent_replay` flag mirror
201
+ * the send-mail contract verbatim.
202
+ *
203
+ */
204
+ export const replyToEmail = (options) => (options.client ?? client).post({
205
+ security: [{ scheme: 'bearer', type: 'http' }],
206
+ url: '/emails/{id}/reply',
207
+ ...options,
208
+ headers: {
209
+ 'Content-Type': 'application/json',
210
+ ...options.headers
211
+ }
212
+ });
187
213
  /**
188
214
  * Replay email webhooks
189
215
  *
@@ -1,2 +1,2 @@
1
- import { $ as AddDomainResponses, $n as ReplayDeliveryResponses, $r as VerifiedDomain, $t as GateDenial, A as getWebhookSecret, An as ListDomainsResponse, Ar as UpdateAccountError, At as DeleteFilterError, B as testEndpoint, Bn as ListEndpointsResponse, Br as UpdateDomainResponses, Bt as DownloadAttachmentsErrors, C as deleteEndpoint, Cn as ListDeliveriesError, Cr as TestEndpointError, Ct as DeleteEmailResponses, D as getAccount, Dn as ListDomainsData, Dr as TestResult, Dt as DeleteEndpointResponse, E as downloadRawEmail, En as ListDeliveriesResponses, Er as TestEndpointResponses, Et as DeleteEndpointErrors, F as listFilters, Fn as ListEmailsResponse, Fr as UpdateDomainData, Ft as DeliverySummary, G as verifyDomain, Gn as ListFiltersErrors, Gr as UpdateEndpointResponse, Gt as DownloadRawEmailErrors, H as updateDomain, Hn as ListEnvelope, Hr as UpdateEndpointError, Ht as DownloadAttachmentsResponses, I as replayDelivery, In as ListEmailsResponses, Ir as UpdateDomainError, It as Domain, J as AddDomainData, Jn as PaginationMeta, Jr as UpdateFilterError, Jt as EmailDetail, K as Account, Kn as ListFiltersResponse, Kr as UpdateEndpointResponses, Kt as DownloadRawEmailResponse, L as replayEmailWebhooks, Ln as ListEndpointsData, Lr as UpdateDomainErrors, Lt as DomainVerifyResult, M as listDomains, Mn as ListEmailsData, Mr as UpdateAccountInput, Mt as DeleteFilterResponse, N as listEmails, Nn as ListEmailsError, Nr as UpdateAccountResponse, Nt as DeleteFilterResponses, O as getEmail, On as ListDomainsError, Or as UnverifiedDomain, Ot as DeleteEndpointResponses, P as listEndpoints, Pn as ListEmailsErrors, Pr as UpdateAccountResponses, Pt as DeliveryStatus, Q as AddDomainResponse, Qn as ReplayDeliveryResponse, Qr as UpdateFilterResponses, Qt as Filter, R as rotateWebhookSecret, Rn as ListEndpointsError, Rr as UpdateDomainInput, Rt as DownloadAttachmentsData, S as deleteEmail, Sn as ListDeliveriesData, Sr as TestEndpointData, St as DeleteEmailResponse, T as downloadAttachments, Tn as ListDeliveriesResponse, Tr as TestEndpointResponse, Tt as DeleteEndpointError, U as updateEndpoint, Un as ListFiltersData, Ur as UpdateEndpointErrors, Ut as DownloadRawEmailData, V as updateAccount, Vn as ListEndpointsResponses, Vr as UpdateEndpointData, Vt as DownloadAttachmentsResponse, W as updateFilter, Wn as ListFiltersError, Wr as UpdateEndpointInput, Wt as DownloadRawEmailError, X as AddDomainErrors, Xn as ReplayDeliveryError, Xr as UpdateFilterInput, Xt as Endpoint, Y as AddDomainError, Yn as ReplayDeliveryData, Yr as UpdateFilterErrors, Yt as EmailSummary, Z as AddDomainInput, Zn as ReplayDeliveryErrors, Zr as UpdateFilterResponse, Zt as ErrorResponse, _ as Options, _n as GetWebhookSecretError, _r as SendMailInput, _t as DeleteDomainResponse, a as PrimitiveApiError, ai as WebhookSecret, an as GetAccountResponses, ar as ReplayResult, at as CreateEndpointResponse, b as createFilter, bn as GetWebhookSecretResponses, br as StorageStats, bt as DeleteEmailError, c as PrimitiveClientOptions, ci as Config, cn as GetEmailErrors, cr as RotateWebhookSecretError, ct as CreateFilterError, d as SendResult, di as RequestOptions, dn as GetStorageStatsData, dr as RotateWebhookSecretResponses, dt as CreateFilterResponse, ei as VerifyDomainData, en as GateFix, er as ReplayEmailWebhooksData, et as ClientOptions, f as SendThreadInput, fi as RequestResult, fn as GetStorageStatsError, fr as SendEmailData, ft as CreateFilterResponses, g as operations, gn as GetWebhookSecretData, gr as SendEmailResponses, gt as DeleteDomainErrors, h as createPrimitiveClient, hn as GetStorageStatsResponses, hr as SendEmailResponse, ht as DeleteDomainError, i as PrimitiveApiClientOptions, ii as VerifyDomainResponses, in as GetAccountResponse, ir as ReplayEmailWebhooksResponses, it as CreateEndpointInput, j as listDeliveries, jn as ListDomainsResponses, jr as UpdateAccountErrors, jt as DeleteFilterErrors, k as getStorageStats, kn as ListDomainsErrors, kr as UpdateAccountData, kt as DeleteFilterData, l as ReplyInput, li as CreateClientConfig, ln as GetEmailResponse, lr as RotateWebhookSecretErrors, lt as CreateFilterErrors, m as createPrimitiveApiClient, mi as Auth, mn as GetStorageStatsResponse, mr as SendEmailErrors, mt as DeleteDomainData, n as ForwardInput, ni as VerifyDomainErrors, nn as GetAccountError, nr as ReplayEmailWebhooksErrors, nt as CreateEndpointError, o as PrimitiveApiErrorDetails, oi as Client, on as GetEmailData, or as ResourceId, ot as CreateEndpointResponses, p as client, pi as ResponseStyle, pn as GetStorageStatsErrors, pr as SendEmailError, pt as Cursor, q as AccountUpdated, qn as ListFiltersResponses, qr as UpdateFilterData, qt as DownloadRawEmailResponses, r as PrimitiveApiClient, ri as VerifyDomainResponse, rn as GetAccountErrors, rr as ReplayEmailWebhooksResponse, rt as CreateEndpointErrors, s as PrimitiveClient, si as ClientOptions$1, sn as GetEmailError, sr as RotateWebhookSecretData, st as CreateFilterData, t as DEFAULT_BASE_URL, ti as VerifyDomainError, tn as GetAccountData, tr as ReplayEmailWebhooksError, tt as CreateEndpointData, u as SendInput, ui as Options$1, un as GetEmailResponses, ur as RotateWebhookSecretResponse, ut as CreateFilterInput, v as addDomain, vn as GetWebhookSecretErrors, vr as SendMailResult, vt as DeleteDomainResponses, w as deleteFilter, wn as ListDeliveriesErrors, wr as TestEndpointErrors, wt as DeleteEndpointData, x as deleteDomain, xn as Limit, xr as SuccessEnvelope, xt as DeleteEmailErrors, y as createEndpoint, yn as GetWebhookSecretResponse, yr as SentEmailStatus, yt as DeleteEmailData, z as sendEmail, zn as ListEndpointsErrors, zr as UpdateDomainResponse, zt as DownloadAttachmentsError } from "../index-DVow4Fjd.js";
2
- export { Account, AccountUpdated, AddDomainData, AddDomainError, AddDomainErrors, AddDomainInput, AddDomainResponse, AddDomainResponses, Auth, ClientOptions, CreateClientConfig, CreateEndpointData, CreateEndpointError, CreateEndpointErrors, CreateEndpointInput, CreateEndpointResponse, CreateEndpointResponses, CreateFilterData, CreateFilterError, CreateFilterErrors, CreateFilterInput, CreateFilterResponse, CreateFilterResponses, Cursor, DEFAULT_BASE_URL, DeleteDomainData, DeleteDomainError, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailData, DeleteEmailError, DeleteEmailErrors, DeleteEmailResponse, DeleteEmailResponses, DeleteEndpointData, DeleteEndpointError, DeleteEndpointErrors, DeleteEndpointResponse, DeleteEndpointResponses, DeleteFilterData, DeleteFilterError, DeleteFilterErrors, DeleteFilterResponse, DeleteFilterResponses, DeliveryStatus, DeliverySummary, Domain, DomainVerifyResult, DownloadAttachmentsData, DownloadAttachmentsError, DownloadAttachmentsErrors, DownloadAttachmentsResponse, DownloadAttachmentsResponses, DownloadRawEmailData, DownloadRawEmailError, DownloadRawEmailErrors, DownloadRawEmailResponse, DownloadRawEmailResponses, EmailDetail, EmailSummary, Endpoint, ErrorResponse, Filter, ForwardInput, GateDenial, GateFix, GetAccountData, GetAccountError, GetAccountErrors, GetAccountResponse, GetAccountResponses, GetEmailData, GetEmailError, GetEmailErrors, GetEmailResponse, GetEmailResponses, GetStorageStatsData, GetStorageStatsError, GetStorageStatsErrors, GetStorageStatsResponse, GetStorageStatsResponses, GetWebhookSecretData, GetWebhookSecretError, GetWebhookSecretErrors, GetWebhookSecretResponse, GetWebhookSecretResponses, Limit, ListDeliveriesData, ListDeliveriesError, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDomainsData, ListDomainsError, ListDomainsErrors, ListDomainsResponse, ListDomainsResponses, ListEmailsData, ListEmailsError, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEndpointsData, ListEndpointsError, ListEndpointsErrors, ListEndpointsResponse, ListEndpointsResponses, ListEnvelope, ListFiltersData, ListFiltersError, ListFiltersErrors, ListFiltersResponse, ListFiltersResponses, Options, PaginationMeta, PrimitiveApiClient, PrimitiveApiClientOptions, PrimitiveApiError, PrimitiveApiErrorDetails, PrimitiveClient, PrimitiveClientOptions, Client as PrimitiveGeneratedApiClient, ClientOptions$1 as PrimitiveGeneratedApiClientOptions, Config as PrimitiveGeneratedApiConfig, Options$1 as PrimitiveGeneratedApiOptions, RequestOptions as PrimitiveGeneratedApiRequestOptions, RequestResult as PrimitiveGeneratedApiRequestResult, ReplayDeliveryData, ReplayDeliveryError, ReplayDeliveryErrors, ReplayDeliveryResponse, ReplayDeliveryResponses, ReplayEmailWebhooksData, ReplayEmailWebhooksError, ReplayEmailWebhooksErrors, ReplayEmailWebhooksResponse, ReplayEmailWebhooksResponses, ReplayResult, ReplyInput, ResourceId, ResponseStyle, RotateWebhookSecretData, RotateWebhookSecretError, RotateWebhookSecretErrors, RotateWebhookSecretResponse, RotateWebhookSecretResponses, SendEmailData, SendEmailError, SendEmailErrors, SendEmailResponse, SendEmailResponses, SendInput, SendMailInput, SendMailResult, SendResult, SendThreadInput, SentEmailStatus, StorageStats, SuccessEnvelope, TestEndpointData, TestEndpointError, TestEndpointErrors, TestEndpointResponse, TestEndpointResponses, TestResult, UnverifiedDomain, UpdateAccountData, UpdateAccountError, UpdateAccountErrors, UpdateAccountInput, UpdateAccountResponse, UpdateAccountResponses, UpdateDomainData, UpdateDomainError, UpdateDomainErrors, UpdateDomainInput, UpdateDomainResponse, UpdateDomainResponses, UpdateEndpointData, UpdateEndpointError, UpdateEndpointErrors, UpdateEndpointInput, UpdateEndpointResponse, UpdateEndpointResponses, UpdateFilterData, UpdateFilterError, UpdateFilterErrors, UpdateFilterInput, UpdateFilterResponse, UpdateFilterResponses, VerifiedDomain, VerifyDomainData, VerifyDomainError, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, WebhookSecret, addDomain, client, createEndpoint, createFilter, createPrimitiveApiClient, createPrimitiveClient, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, operations, replayDelivery, replayEmailWebhooks, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
1
+ import { $ as AddDomainResponse, $n as ReplayDeliveryErrors, $r as UpdateEndpointResponses, $t as ErrorResponse, A as getWebhookSecret, An as ListDomainsError, Ar as TestEndpointError, At as DeleteFilterData, B as sendEmail, Bn as ListEndpointsError, Br as UpdateAccountResponse, Bt as DownloadAttachmentsError, C as deleteEndpoint, Cn as Limit, Cr as SendEmailResponses, Ct as DeleteEmailResponse, D as getAccount, Dn as ListDeliveriesResponse, Dr as StorageStats, Dt as DeleteEndpointErrors, E as downloadRawEmail, En as ListDeliveriesErrors, Er as SentEmailStatus, Et as DeleteEndpointError, F as listFilters, Fn as ListEmailsError, Fr as UnverifiedDomain, Ft as DeliveryStatus, G as updateFilter, Gn as ListFiltersData, Gr as UpdateDomainInput, Gt as DownloadRawEmailError, H as updateAccount, Hn as ListEndpointsResponse, Hr as UpdateDomainData, Ht as DownloadAttachmentsResponse, I as replayDelivery, In as ListEmailsErrors, Ir as UpdateAccountData, It as DeliverySummary, J as AccountUpdated, Jn as ListFiltersResponse, Jr as UpdateEndpointData, Jt as DownloadRawEmailResponses, K as verifyDomain, Kn as ListFiltersError, Kr as UpdateDomainResponse, Kt as DownloadRawEmailErrors, L as replayEmailWebhooks, Ln as ListEmailsResponse, Lr as UpdateAccountError, Lt as Domain, M as listDomains, Mn as ListDomainsResponse, Mr as TestEndpointResponse, Mt as DeleteFilterErrors, N as listEmails, Nn as ListDomainsResponses, Nr as TestEndpointResponses, Nt as DeleteFilterResponse, O as getEmail, On as ListDeliveriesResponses, Or as SuccessEnvelope, Ot as DeleteEndpointResponse, P as listEndpoints, Pn as ListEmailsData, Pr as TestResult, Pt as DeleteFilterResponses, Q as AddDomainInput, Qn as ReplayDeliveryError, Qr as UpdateEndpointResponse, Qt as Endpoint, R as replyToEmail, Rn as ListEmailsResponses, Rr as UpdateAccountErrors, Rt as DomainVerifyResult, S as deleteEmail, Sn as GetWebhookSecretResponses, Sr as SendEmailResponse, St as DeleteEmailErrors, T as downloadAttachments, Tn as ListDeliveriesError, Tr as SendMailResult, Tt as DeleteEndpointData, U as updateDomain, Un as ListEndpointsResponses, Ur as UpdateDomainError, Ut as DownloadAttachmentsResponses, V as testEndpoint, Vn as ListEndpointsErrors, Vr as UpdateAccountResponses, Vt as DownloadAttachmentsErrors, W as updateEndpoint, Wn as ListEnvelope, Wr as UpdateDomainErrors, Wt as DownloadRawEmailData, X as AddDomainError, Xn as PaginationMeta, Xr as UpdateEndpointErrors, Xt as EmailDetailReply, Y as AddDomainData, Yn as ListFiltersResponses, Yr as UpdateEndpointError, Yt as EmailDetail, Z as AddDomainErrors, Zn as ReplayDeliveryData, Zr as UpdateEndpointInput, Zt as EmailSummary, _ as Options, _i as Options$1, _n as GetStorageStatsResponses, _r as RotateWebhookSecretResponse, _t as DeleteDomainErrors, a as PrimitiveApiError, ai as UpdateFilterResponses, an as GetAccountErrors, ar as ReplayEmailWebhooksResponse, at as CreateEndpointInput, b as createFilter, bi as ResponseStyle, bn as GetWebhookSecretErrors, br as SendEmailError, bt as DeleteEmailData, c as PrimitiveClientOptions, ci as VerifyDomainError, cn as GetEmailData, cr as ReplyToEmailData, ct as CreateFilterData, d as SendResult, di as VerifyDomainResponses, dn as GetEmailResponse, dr as ReplyToEmailResponse, dt as CreateFilterInput, ei as UpdateFilterData, en as Filter, er as ReplayDeliveryResponse, et as AddDomainResponses, f as SendThreadInput, fi as WebhookSecret, fn as GetEmailResponses, fr as ReplyToEmailResponses, ft as CreateFilterResponse, g as operations, gi as CreateClientConfig, gn as GetStorageStatsResponse, gr as RotateWebhookSecretErrors, gt as DeleteDomainError, h as createPrimitiveClient, hi as Config, hn as GetStorageStatsErrors, hr as RotateWebhookSecretError, ht as DeleteDomainData, i as PrimitiveApiClientOptions, ii as UpdateFilterResponse, in as GetAccountError, ir as ReplayEmailWebhooksErrors, it as CreateEndpointErrors, j as listDeliveries, jn as ListDomainsErrors, jr as TestEndpointErrors, jt as DeleteFilterError, k as getStorageStats, kn as ListDomainsData, kr as TestEndpointData, kt as DeleteEndpointResponses, l as ReplyInput, li as VerifyDomainErrors, ln as GetEmailError, lr as ReplyToEmailError, lt as CreateFilterError, m as createPrimitiveApiClient, mi as ClientOptions$1, mn as GetStorageStatsError, mr as RotateWebhookSecretData, mt as Cursor, n as ForwardInput, ni as UpdateFilterErrors, nn as GateFix, nr as ReplayEmailWebhooksData, nt as CreateEndpointData, o as PrimitiveApiErrorDetails, oi as VerifiedDomain, on as GetAccountResponse, or as ReplayEmailWebhooksResponses, ot as CreateEndpointResponse, p as client, pi as Client, pn as GetStorageStatsData, pr as ResourceId, pt as CreateFilterResponses, q as Account, qn as ListFiltersErrors, qr as UpdateDomainResponses, qt as DownloadRawEmailResponse, r as PrimitiveApiClient, ri as UpdateFilterInput, rn as GetAccountData, rr as ReplayEmailWebhooksError, rt as CreateEndpointError, s as PrimitiveClient, si as VerifyDomainData, sn as GetAccountResponses, sr as ReplayResult, st as CreateEndpointResponses, t as DEFAULT_BASE_URL, ti as UpdateFilterError, tn as GateDenial, tr as ReplayDeliveryResponses, tt as ClientOptions, u as SendInput, ui as VerifyDomainResponse, un as GetEmailErrors, ur as ReplyToEmailErrors, ut as CreateFilterErrors, v as addDomain, vi as RequestOptions, vn as GetWebhookSecretData, vr as RotateWebhookSecretResponses, vt as DeleteDomainResponse, w as deleteFilter, wn as ListDeliveriesData, wr as SendMailInput, wt as DeleteEmailResponses, x as deleteDomain, xi as Auth, xn as GetWebhookSecretResponse, xr as SendEmailErrors, xt as DeleteEmailError, y as createEndpoint, yi as RequestResult, yn as GetWebhookSecretError, yr as SendEmailData, yt as DeleteDomainResponses, z as rotateWebhookSecret, zn as ListEndpointsData, zr as UpdateAccountInput, zt as DownloadAttachmentsData } from "../index-K4KbjppU.js";
2
+ export { Account, AccountUpdated, AddDomainData, AddDomainError, AddDomainErrors, AddDomainInput, AddDomainResponse, AddDomainResponses, Auth, ClientOptions, CreateClientConfig, CreateEndpointData, CreateEndpointError, CreateEndpointErrors, CreateEndpointInput, CreateEndpointResponse, CreateEndpointResponses, CreateFilterData, CreateFilterError, CreateFilterErrors, CreateFilterInput, CreateFilterResponse, CreateFilterResponses, Cursor, DEFAULT_BASE_URL, DeleteDomainData, DeleteDomainError, DeleteDomainErrors, DeleteDomainResponse, DeleteDomainResponses, DeleteEmailData, DeleteEmailError, DeleteEmailErrors, DeleteEmailResponse, DeleteEmailResponses, DeleteEndpointData, DeleteEndpointError, DeleteEndpointErrors, DeleteEndpointResponse, DeleteEndpointResponses, DeleteFilterData, DeleteFilterError, DeleteFilterErrors, DeleteFilterResponse, DeleteFilterResponses, DeliveryStatus, DeliverySummary, Domain, DomainVerifyResult, DownloadAttachmentsData, DownloadAttachmentsError, DownloadAttachmentsErrors, DownloadAttachmentsResponse, DownloadAttachmentsResponses, DownloadRawEmailData, DownloadRawEmailError, DownloadRawEmailErrors, DownloadRawEmailResponse, DownloadRawEmailResponses, EmailDetail, EmailDetailReply, EmailSummary, Endpoint, ErrorResponse, Filter, ForwardInput, GateDenial, GateFix, GetAccountData, GetAccountError, GetAccountErrors, GetAccountResponse, GetAccountResponses, GetEmailData, GetEmailError, GetEmailErrors, GetEmailResponse, GetEmailResponses, GetStorageStatsData, GetStorageStatsError, GetStorageStatsErrors, GetStorageStatsResponse, GetStorageStatsResponses, GetWebhookSecretData, GetWebhookSecretError, GetWebhookSecretErrors, GetWebhookSecretResponse, GetWebhookSecretResponses, Limit, ListDeliveriesData, ListDeliveriesError, ListDeliveriesErrors, ListDeliveriesResponse, ListDeliveriesResponses, ListDomainsData, ListDomainsError, ListDomainsErrors, ListDomainsResponse, ListDomainsResponses, ListEmailsData, ListEmailsError, ListEmailsErrors, ListEmailsResponse, ListEmailsResponses, ListEndpointsData, ListEndpointsError, ListEndpointsErrors, ListEndpointsResponse, ListEndpointsResponses, ListEnvelope, ListFiltersData, ListFiltersError, ListFiltersErrors, ListFiltersResponse, ListFiltersResponses, Options, PaginationMeta, PrimitiveApiClient, PrimitiveApiClientOptions, PrimitiveApiError, PrimitiveApiErrorDetails, PrimitiveClient, PrimitiveClientOptions, Client as PrimitiveGeneratedApiClient, ClientOptions$1 as PrimitiveGeneratedApiClientOptions, Config as PrimitiveGeneratedApiConfig, Options$1 as PrimitiveGeneratedApiOptions, RequestOptions as PrimitiveGeneratedApiRequestOptions, RequestResult as PrimitiveGeneratedApiRequestResult, ReplayDeliveryData, ReplayDeliveryError, ReplayDeliveryErrors, ReplayDeliveryResponse, ReplayDeliveryResponses, ReplayEmailWebhooksData, ReplayEmailWebhooksError, ReplayEmailWebhooksErrors, ReplayEmailWebhooksResponse, ReplayEmailWebhooksResponses, ReplayResult, ReplyInput, ReplyToEmailData, ReplyToEmailError, ReplyToEmailErrors, ReplyToEmailResponse, ReplyToEmailResponses, ResourceId, ResponseStyle, RotateWebhookSecretData, RotateWebhookSecretError, RotateWebhookSecretErrors, RotateWebhookSecretResponse, RotateWebhookSecretResponses, SendEmailData, SendEmailError, SendEmailErrors, SendEmailResponse, SendEmailResponses, SendInput, SendMailInput, SendMailResult, SendResult, SendThreadInput, SentEmailStatus, StorageStats, SuccessEnvelope, TestEndpointData, TestEndpointError, TestEndpointErrors, TestEndpointResponse, TestEndpointResponses, TestResult, UnverifiedDomain, UpdateAccountData, UpdateAccountError, UpdateAccountErrors, UpdateAccountInput, UpdateAccountResponse, UpdateAccountResponses, UpdateDomainData, UpdateDomainError, UpdateDomainErrors, UpdateDomainInput, UpdateDomainResponse, UpdateDomainResponses, UpdateEndpointData, UpdateEndpointError, UpdateEndpointErrors, UpdateEndpointInput, UpdateEndpointResponse, UpdateEndpointResponses, UpdateFilterData, UpdateFilterError, UpdateFilterErrors, UpdateFilterInput, UpdateFilterResponse, UpdateFilterResponses, VerifiedDomain, VerifyDomainData, VerifyDomainError, VerifyDomainErrors, VerifyDomainResponse, VerifyDomainResponses, WebhookSecret, addDomain, client, createEndpoint, createFilter, createPrimitiveApiClient, createPrimitiveClient, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, operations, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
package/dist/api/index.js CHANGED
@@ -194,43 +194,50 @@ export class PrimitiveClient extends PrimitiveApiClient {
194
194
  client: this.client,
195
195
  responseStyle: "fields",
196
196
  });
197
- const response = result.response;
198
- if (result.error) {
199
- const parsed = parseApiErrorPayload(result.error);
200
- throw new PrimitiveApiError(parsed.message, {
201
- payload: result.error,
202
- status: response?.status,
203
- code: parsed.code,
204
- gates: parsed.gates,
205
- requestId: parsed.requestId,
206
- retryAfter: parseRetryAfterHeader(response),
207
- details: parsed.details,
208
- });
209
- }
210
- if (!result.data?.data) {
211
- throw new PrimitiveApiError("Primitive API returned no send result", {
212
- payload: result,
213
- status: response?.status,
214
- });
215
- }
216
- return mapSendResult(result.data.data);
197
+ return unwrapSendResult(result);
217
198
  }
199
+ /**
200
+ * Reply to an inbound email.
201
+ *
202
+ * Calls `POST /emails/{id}/reply`. The server derives recipients
203
+ * (Reply-To, then From, then sender), subject (`Re: <parent>` with
204
+ * idempotent prefix), and threading headers (`In-Reply-To`,
205
+ * `References`) from the stored inbound row. The customer controls
206
+ * only the body, an optional `from` override, and the `wait` flag.
207
+ *
208
+ * Subject overrides are intentionally not supported: Gmail's
209
+ * Conversation View needs both a References match and a normalized-
210
+ * subject match to thread, so a custom subject silently breaks the
211
+ * thread for half the recipient population.
212
+ */
218
213
  async reply(email, input) {
219
214
  const resolved = typeof input === "string" ? { text: input } : input;
220
- return this.send({
221
- from: resolved.from ?? email.receivedBy,
222
- to: email.replyTarget.address,
223
- subject: resolved.subject ?? email.replySubject,
224
- bodyText: resolved.text,
225
- thread: {
226
- ...(email.thread.messageId
227
- ? { inReplyTo: email.thread.messageId }
228
- : {}),
229
- references: email.thread.messageId
230
- ? [...email.thread.references, email.thread.messageId]
231
- : email.thread.references,
232
- },
215
+ // Reject the subject override at runtime so a JS caller (no TS
216
+ // types) gets the same loud error as a TS caller. Without this,
217
+ // `client.reply(email, { text, subject: "Custom" })` silently
218
+ // dropped subject and sent a "Re:" reply, breaking Gmail
219
+ // threading without telling the caller. Mirrors Python's
220
+ // ValueError. Checked before the empty-body check so passing
221
+ // ONLY a subject surfaces the more informative error.
222
+ if ("subject" in resolved) {
223
+ throw new TypeError("reply does not support a subject override; the server prepends 'Re:' to the parent's subject for thread continuity");
224
+ }
225
+ if (!resolved.text && !resolved.html) {
226
+ throw new TypeError("reply requires text or html");
227
+ }
228
+ const body = {
229
+ ...(resolved.text !== undefined ? { body_text: resolved.text } : {}),
230
+ ...(resolved.html !== undefined ? { body_html: resolved.html } : {}),
231
+ ...(resolved.from !== undefined ? { from: resolved.from } : {}),
232
+ ...(resolved.wait !== undefined ? { wait: resolved.wait } : {}),
233
+ };
234
+ const result = await generatedOperations.replyToEmail({
235
+ body,
236
+ path: { id: email.id },
237
+ client: this.client,
238
+ responseStyle: "fields",
233
239
  });
240
+ return unwrapSendResult(result);
234
241
  }
235
242
  async forward(email, input) {
236
243
  validateForwardInput(input);
@@ -260,6 +267,34 @@ function buildForwardText(email, intro) {
260
267
  ];
261
268
  return lines.join("\n").trimEnd();
262
269
  }
270
+ /**
271
+ * Shared response handler for `send`, `reply`, and any future
272
+ * operation that returns a SendMailResult envelope. Unifies the
273
+ * error-mapping path so the network call sites only have to invoke
274
+ * the generated operation.
275
+ */
276
+ function unwrapSendResult(result) {
277
+ const response = result.response;
278
+ if (result.error) {
279
+ const parsed = parseApiErrorPayload(result.error);
280
+ throw new PrimitiveApiError(parsed.message, {
281
+ payload: result.error,
282
+ status: response?.status,
283
+ code: parsed.code,
284
+ gates: parsed.gates,
285
+ requestId: parsed.requestId,
286
+ retryAfter: parseRetryAfterHeader(response),
287
+ details: parsed.details,
288
+ });
289
+ }
290
+ if (!result.data?.data) {
291
+ throw new PrimitiveApiError("Primitive API returned no send result", {
292
+ payload: result,
293
+ status: response?.status,
294
+ });
295
+ }
296
+ return mapSendResult(result.data.data);
297
+ }
263
298
  function mapSendResult(result) {
264
299
  return {
265
300
  id: result.id,
@@ -270,6 +305,10 @@ function mapSendResult(result) {
270
305
  clientIdempotencyKey: result.client_idempotency_key,
271
306
  requestId: result.request_id,
272
307
  contentHash: result.content_hash,
308
+ // Default to false if the server omits the field (old-format
309
+ // response, mocked partial response in a customer's tests). The
310
+ // type signature claims `boolean`, so undefined would be a lie.
311
+ idempotentReplay: result.idempotent_replay ?? false,
273
312
  ...(result.delivery_status !== undefined
274
313
  ? { deliveryStatus: result.delivery_status }
275
314
  : {}),
@@ -633,6 +633,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
633
633
  listFilters: () => listFilters,
634
634
  replayDelivery: () => replayDelivery,
635
635
  replayEmailWebhooks: () => replayEmailWebhooks,
636
+ replyToEmail: () => replyToEmail,
636
637
  rotateWebhookSecret: () => rotateWebhookSecret,
637
638
  sendEmail: () => sendEmail,
638
639
  testEndpoint: () => testEndpoint,
@@ -872,6 +873,35 @@ const downloadAttachments = (options) => (options.client ?? client$1).get({
872
873
  ...options
873
874
  });
874
875
  /**
876
+ * Reply to an inbound email
877
+ *
878
+ * Sends an outbound reply to the inbound email identified by `id`.
879
+ * Threading headers (`In-Reply-To`, `References`), recipient
880
+ * derivation (Reply-To, then From, then bare sender), and the
881
+ * `Re:` subject prefix are all derived server-side from the
882
+ * stored inbound row. The request body carries only the message
883
+ * body and optional `wait` flag; passing any header or recipient
884
+ * override is rejected by the schema (`additionalProperties:
885
+ * false`).
886
+ *
887
+ * Forwards through the same gates as `/send-mail`: the response
888
+ * status, error envelope, and `idempotent_replay` flag mirror
889
+ * the send-mail contract verbatim.
890
+ *
891
+ */
892
+ const replyToEmail = (options) => (options.client ?? client$1).post({
893
+ security: [{
894
+ scheme: "bearer",
895
+ type: "http"
896
+ }],
897
+ url: "/emails/{id}/reply",
898
+ ...options,
899
+ headers: {
900
+ "Content-Type": "application/json",
901
+ ...options.headers
902
+ }
903
+ });
904
+ /**
875
905
  * Replay email webhooks
876
906
  *
877
907
  * Re-delivers the webhook payload for this email to all active
@@ -1211,7 +1241,7 @@ var PrimitiveApiClient = class {
1211
1241
  var PrimitiveClient = class extends PrimitiveApiClient {
1212
1242
  async send(input) {
1213
1243
  validateSendInput(input);
1214
- const result = await sendEmail({
1244
+ return unwrapSendResult(await sendEmail({
1215
1245
  body: {
1216
1246
  from: input.from,
1217
1247
  to: input.to,
@@ -1226,38 +1256,37 @@ var PrimitiveClient = class extends PrimitiveApiClient {
1226
1256
  ...input.idempotencyKey ? { headers: { "Idempotency-Key": input.idempotencyKey } } : {},
1227
1257
  client: this.client,
1228
1258
  responseStyle: "fields"
1229
- });
1230
- const response = result.response;
1231
- if (result.error) {
1232
- const parsed = parseApiErrorPayload(result.error);
1233
- throw new PrimitiveApiError(parsed.message, {
1234
- payload: result.error,
1235
- status: response?.status,
1236
- code: parsed.code,
1237
- gates: parsed.gates,
1238
- requestId: parsed.requestId,
1239
- retryAfter: parseRetryAfterHeader(response),
1240
- details: parsed.details
1241
- });
1242
- }
1243
- if (!result.data?.data) throw new PrimitiveApiError("Primitive API returned no send result", {
1244
- payload: result,
1245
- status: response?.status
1246
- });
1247
- return mapSendResult(result.data.data);
1259
+ }));
1248
1260
  }
1261
+ /**
1262
+ * Reply to an inbound email.
1263
+ *
1264
+ * Calls `POST /emails/{id}/reply`. The server derives recipients
1265
+ * (Reply-To, then From, then sender), subject (`Re: <parent>` with
1266
+ * idempotent prefix), and threading headers (`In-Reply-To`,
1267
+ * `References`) from the stored inbound row. The customer controls
1268
+ * only the body, an optional `from` override, and the `wait` flag.
1269
+ *
1270
+ * Subject overrides are intentionally not supported: Gmail's
1271
+ * Conversation View needs both a References match and a normalized-
1272
+ * subject match to thread, so a custom subject silently breaks the
1273
+ * thread for half the recipient population.
1274
+ */
1249
1275
  async reply(email, input) {
1250
1276
  const resolved = typeof input === "string" ? { text: input } : input;
1251
- return this.send({
1252
- from: resolved.from ?? email.receivedBy,
1253
- to: email.replyTarget.address,
1254
- subject: resolved.subject ?? email.replySubject,
1255
- bodyText: resolved.text,
1256
- thread: {
1257
- ...email.thread.messageId ? { inReplyTo: email.thread.messageId } : {},
1258
- references: email.thread.messageId ? [...email.thread.references, email.thread.messageId] : email.thread.references
1259
- }
1260
- });
1277
+ if ("subject" in resolved) throw new TypeError("reply does not support a subject override; the server prepends 'Re:' to the parent's subject for thread continuity");
1278
+ if (!resolved.text && !resolved.html) throw new TypeError("reply requires text or html");
1279
+ return unwrapSendResult(await replyToEmail({
1280
+ body: {
1281
+ ...resolved.text !== void 0 ? { body_text: resolved.text } : {},
1282
+ ...resolved.html !== void 0 ? { body_html: resolved.html } : {},
1283
+ ...resolved.from !== void 0 ? { from: resolved.from } : {},
1284
+ ...resolved.wait !== void 0 ? { wait: resolved.wait } : {}
1285
+ },
1286
+ path: { id: email.id },
1287
+ client: this.client,
1288
+ responseStyle: "fields"
1289
+ }));
1261
1290
  }
1262
1291
  async forward(email, input) {
1263
1292
  validateForwardInput(input);
@@ -1282,6 +1311,32 @@ function buildForwardText(email, intro) {
1282
1311
  email.text ?? ""
1283
1312
  ].join("\n").trimEnd();
1284
1313
  }
1314
+ /**
1315
+ * Shared response handler for `send`, `reply`, and any future
1316
+ * operation that returns a SendMailResult envelope. Unifies the
1317
+ * error-mapping path so the network call sites only have to invoke
1318
+ * the generated operation.
1319
+ */
1320
+ function unwrapSendResult(result) {
1321
+ const response = result.response;
1322
+ if (result.error) {
1323
+ const parsed = parseApiErrorPayload(result.error);
1324
+ throw new PrimitiveApiError(parsed.message, {
1325
+ payload: result.error,
1326
+ status: response?.status,
1327
+ code: parsed.code,
1328
+ gates: parsed.gates,
1329
+ requestId: parsed.requestId,
1330
+ retryAfter: parseRetryAfterHeader(response),
1331
+ details: parsed.details
1332
+ });
1333
+ }
1334
+ if (!result.data?.data) throw new PrimitiveApiError("Primitive API returned no send result", {
1335
+ payload: result,
1336
+ status: response?.status
1337
+ });
1338
+ return mapSendResult(result.data.data);
1339
+ }
1285
1340
  function mapSendResult(result) {
1286
1341
  return {
1287
1342
  id: result.id,
@@ -1292,6 +1347,7 @@ function mapSendResult(result) {
1292
1347
  clientIdempotencyKey: result.client_idempotency_key,
1293
1348
  requestId: result.request_id,
1294
1349
  contentHash: result.content_hash,
1350
+ idempotentReplay: result.idempotent_replay ?? false,
1295
1351
  ...result.delivery_status !== void 0 ? { deliveryStatus: result.delivery_status } : {},
1296
1352
  ...result.smtp_response_code !== void 0 ? { smtpResponseCode: result.smtp_response_code } : {},
1297
1353
  ...result.smtp_response_text !== void 0 ? { smtpResponseText: result.smtp_response_text } : {}
@@ -1308,4 +1364,4 @@ function client(options = {}) {
1308
1364
  }
1309
1365
  const operations = sdk_gen_exports;
1310
1366
  //#endregion
1311
- export { sendEmail as A, listDomains as C, replayDelivery as D, listFilters as E, updateFilter as F, verifyDomain as I, updateAccount as M, updateDomain as N, replayEmailWebhooks as O, updateEndpoint as P, listDeliveries as S, listEndpoints as T, downloadRawEmail as _, client as a, getStorageStats as b, operations as c, createFilter as d, deleteDomain as f, downloadAttachments as g, deleteFilter as h, PrimitiveClient as i, testEndpoint as j, rotateWebhookSecret as k, addDomain as l, deleteEndpoint as m, PrimitiveApiClient as n, createPrimitiveApiClient as o, deleteEmail as p, PrimitiveApiError as r, createPrimitiveClient as s, DEFAULT_BASE_URL as t, createEndpoint as u, getAccount as v, listEmails as w, getWebhookSecret as x, getEmail as y };
1367
+ export { rotateWebhookSecret as A, listDomains as C, replayDelivery as D, listFilters as E, updateEndpoint as F, updateFilter as I, verifyDomain as L, testEndpoint as M, updateAccount as N, replayEmailWebhooks as O, updateDomain as P, listDeliveries as S, listEndpoints as T, downloadRawEmail as _, client as a, getStorageStats as b, operations as c, createFilter as d, deleteDomain as f, downloadAttachments as g, deleteFilter as h, PrimitiveClient as i, sendEmail as j, replyToEmail as k, addDomain as l, deleteEndpoint as m, PrimitiveApiClient as n, createPrimitiveApiClient as o, deleteEmail as p, PrimitiveApiError as r, createPrimitiveClient as s, DEFAULT_BASE_URL as t, createEndpoint as u, getAccount as v, listEmails as w, getWebhookSecret as x, getEmail as y };
@@ -347,7 +347,7 @@ type PaginationMeta = {
347
347
  type ErrorResponse = {
348
348
  success: boolean;
349
349
  error: {
350
- code: 'unauthorized' | 'forbidden' | 'not_found' | 'validation_error' | 'rate_limit_exceeded' | 'internal_error' | 'conflict' | 'mx_conflict' | 'outbound_disabled' | 'cannot_send_from_domain' | 'recipient_not_allowed' | 'outbound_key_missing' | 'outbound_unreachable' | 'outbound_key_invalid' | 'outbound_capacity_exhausted' | 'outbound_response_malformed' | 'outbound_relay_failed';
350
+ code: 'unauthorized' | 'forbidden' | 'not_found' | 'validation_error' | 'rate_limit_exceeded' | 'internal_error' | 'conflict' | 'mx_conflict' | 'outbound_disabled' | 'cannot_send_from_domain' | 'recipient_not_allowed' | 'outbound_key_missing' | 'outbound_unreachable' | 'outbound_key_invalid' | 'outbound_capacity_exhausted' | 'outbound_response_malformed' | 'outbound_relay_failed' | 'inbound_not_repliable';
351
351
  message: string;
352
352
  /**
353
353
  * Optional structured data that callers can inspect to recover
@@ -579,6 +579,14 @@ type EmailDetail = {
579
579
  sender: string;
580
580
  recipient: string;
581
581
  subject?: string | null;
582
+ /**
583
+ * Plain-text body parsed from the inbound MIME, matching the `email.parsed.body_text` field on the webhook payload. Null when the message had no text part or parsing failed.
584
+ */
585
+ body_text?: string | null;
586
+ /**
587
+ * HTML body parsed from the inbound MIME, matching the `email.parsed.body_html` field on the webhook payload. Null when the message had no HTML part or parsing failed.
588
+ */
589
+ body_html?: string | null;
582
590
  status: 'pending' | 'accepted' | 'completed' | 'rejected';
583
591
  domain: string;
584
592
  spam_score?: number | null;
@@ -607,6 +615,42 @@ type EmailDetail = {
607
615
  * Parsed to address (same as recipient)
608
616
  */
609
617
  to_email: string;
618
+ /**
619
+ * True when the inbound's sender address has a matching grant
620
+ * in the org's known-send-addresses list. Advisory: a true
621
+ * value does not by itself guarantee that a reply will be
622
+ * accepted by send-mail's gates; the per-send check at send
623
+ * time remains authoritative.
624
+ *
625
+ */
626
+ from_known_address?: boolean;
627
+ /**
628
+ * Sent emails recorded as replies to this inbound, in send
629
+ * order (ascending). Populated when a customer's send-mail
630
+ * request carries an `in_reply_to` Message-ID that matches
631
+ * this inbound's `message_id` in the same org. Includes
632
+ * attempts that were gate-denied, so the array reflects every
633
+ * recorded reply attempt regardless of outcome.
634
+ *
635
+ */
636
+ replies: Array<EmailDetailReply>;
637
+ };
638
+ type EmailDetailReply = {
639
+ /**
640
+ * Sent-email row id.
641
+ */
642
+ id: string;
643
+ status: SentEmailStatus;
644
+ /**
645
+ * Recipient address as recorded on the sent_emails row.
646
+ */
647
+ to_address: string;
648
+ subject?: string | null;
649
+ created_at: string;
650
+ /**
651
+ * Outbound relay queue identifier when available.
652
+ */
653
+ queue_id?: string | null;
610
654
  };
611
655
  type SendMailInput = {
612
656
  /**
@@ -648,6 +692,44 @@ type SendMailInput = {
648
692
  };
649
693
  type SentEmailStatus = 'queued' | 'submitted_to_agent' | 'agent_failed' | 'unknown' | 'delivered' | 'bounced' | 'deferred' | 'wait_timeout';
650
694
  type DeliveryStatus = 'delivered' | 'bounced' | 'deferred' | 'wait_timeout';
695
+ /**
696
+ * Body shape for `/emails/{id}/reply`. Intentionally narrow:
697
+ * recipients (`to`), subject, and threading headers
698
+ * (`in_reply_to`, `references`) are derived server-side from
699
+ * the inbound row referenced by the path id and are rejected by
700
+ * `additionalProperties` if passed (returns 400).
701
+ *
702
+ * `from` IS allowed because of legitimate use cases (display-name
703
+ * addition, replying from a different verified outbound address,
704
+ * multi-team triage). Send-mail's per-send `canSendFrom` gate
705
+ * validates the from-domain regardless, so the override carries
706
+ * no extra privilege.
707
+ *
708
+ */
709
+ type ReplyInput$1 = {
710
+ /**
711
+ * Plain-text reply body. At least one of body_text or body_html is required. The combined UTF-8 byte length of body_text and body_html must be at most 262144 bytes (same cap as send-mail).
712
+ */
713
+ body_text?: string;
714
+ /**
715
+ * HTML reply body. At least one of body_text or body_html is required.
716
+ */
717
+ body_html?: string;
718
+ /**
719
+ * Optional override for the reply's From header. Defaults to
720
+ * the inbound's recipient. Use to add a display name (`"Acme
721
+ * Support" <agent@company.com>`) or to reply from a different
722
+ * verified outbound address (e.g. multi-team routing where
723
+ * support@ triages to billing@). The from-domain must be a
724
+ * verified outbound domain for your org, same as send-mail.
725
+ *
726
+ */
727
+ from?: string;
728
+ /**
729
+ * When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics.
730
+ */
731
+ wait?: boolean;
732
+ };
651
733
  type SendMailResult = {
652
734
  /**
653
735
  * Persisted sent-email attempt ID.
@@ -687,6 +769,15 @@ type SendMailResult = {
687
769
  * SMTP response text from the first downstream delivery outcome when wait is true.
688
770
  */
689
771
  smtp_response_text?: string;
772
+ /**
773
+ * True when the response replays a previously-recorded send
774
+ * keyed by `client_idempotency_key` (same key, same canonical
775
+ * payload). False on a fresh send and on gate-denied
776
+ * responses. Lets callers branch on cache state without
777
+ * diffing fields.
778
+ *
779
+ */
780
+ idempotent_replay: boolean;
690
781
  };
691
782
  type Endpoint = {
692
783
  id: string;
@@ -1359,6 +1450,68 @@ type DownloadAttachmentsResponses = {
1359
1450
  200: Blob | File;
1360
1451
  };
1361
1452
  type DownloadAttachmentsResponse = DownloadAttachmentsResponses[keyof DownloadAttachmentsResponses];
1453
+ type ReplyToEmailData = {
1454
+ body: ReplyInput$1;
1455
+ path: {
1456
+ /**
1457
+ * Resource UUID
1458
+ */
1459
+ id: string;
1460
+ };
1461
+ query?: never;
1462
+ url: '/emails/{id}/reply';
1463
+ };
1464
+ type ReplyToEmailErrors = {
1465
+ /**
1466
+ * Invalid request parameters
1467
+ */
1468
+ 400: ErrorResponse;
1469
+ /**
1470
+ * Invalid or missing API key
1471
+ */
1472
+ 401: ErrorResponse;
1473
+ /**
1474
+ * Authenticated caller lacks permission for the operation
1475
+ */
1476
+ 403: ErrorResponse;
1477
+ /**
1478
+ * Resource not found
1479
+ */
1480
+ 404: ErrorResponse;
1481
+ /**
1482
+ * Inbound is not repliable: the row exists but lacks a
1483
+ * `message_id` (no thread anchor) or a `recipient` (cannot
1484
+ * derive the From address).
1485
+ *
1486
+ */
1487
+ 422: ErrorResponse;
1488
+ /**
1489
+ * Rate limit exceeded
1490
+ */
1491
+ 429: ErrorResponse;
1492
+ /**
1493
+ * Primitive encountered an internal error
1494
+ */
1495
+ 500: ErrorResponse;
1496
+ /**
1497
+ * Primitive could not complete the downstream SMTP request
1498
+ */
1499
+ 502: ErrorResponse;
1500
+ /**
1501
+ * Primitive is temporarily unable to process the request
1502
+ */
1503
+ 503: ErrorResponse;
1504
+ };
1505
+ type ReplyToEmailError = ReplyToEmailErrors[keyof ReplyToEmailErrors];
1506
+ type ReplyToEmailResponses = {
1507
+ /**
1508
+ * Outbound relay result
1509
+ */
1510
+ 200: SuccessEnvelope & {
1511
+ data?: SendMailResult;
1512
+ };
1513
+ };
1514
+ type ReplyToEmailResponse = ReplyToEmailResponses[keyof ReplyToEmailResponses];
1362
1515
  type ReplayEmailWebhooksData = {
1363
1516
  body?: never;
1364
1517
  path: {
@@ -1829,7 +1982,7 @@ type SendEmailResponses = {
1829
1982
  };
1830
1983
  type SendEmailResponse = SendEmailResponses[keyof SendEmailResponses];
1831
1984
  declare namespace sdk_gen_d_exports {
1832
- export { Options, addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, replayDelivery, replayEmailWebhooks, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
1985
+ export { Options, addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
1833
1986
  }
1834
1987
  type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options$1<TData, ThrowOnError, TResponse> & {
1835
1988
  /**
@@ -1948,6 +2101,24 @@ declare const downloadRawEmail: <ThrowOnError extends boolean = false>(options:
1948
2101
  *
1949
2102
  */
1950
2103
  declare const downloadAttachments: <ThrowOnError extends boolean = false>(options: Options<DownloadAttachmentsData, ThrowOnError>) => RequestResult<DownloadAttachmentsResponses, DownloadAttachmentsErrors, ThrowOnError, "fields">;
2104
+ /**
2105
+ * Reply to an inbound email
2106
+ *
2107
+ * Sends an outbound reply to the inbound email identified by `id`.
2108
+ * Threading headers (`In-Reply-To`, `References`), recipient
2109
+ * derivation (Reply-To, then From, then bare sender), and the
2110
+ * `Re:` subject prefix are all derived server-side from the
2111
+ * stored inbound row. The request body carries only the message
2112
+ * body and optional `wait` flag; passing any header or recipient
2113
+ * override is rejected by the schema (`additionalProperties:
2114
+ * false`).
2115
+ *
2116
+ * Forwards through the same gates as `/send-mail`: the response
2117
+ * status, error envelope, and `idempotent_replay` flag mirror
2118
+ * the send-mail contract verbatim.
2119
+ *
2120
+ */
2121
+ declare const replyToEmail: <ThrowOnError extends boolean = false>(options: Options<ReplyToEmailData, ThrowOnError>) => RequestResult<ReplyToEmailResponses, ReplyToEmailErrors, ThrowOnError, "fields">;
1951
2122
  /**
1952
2123
  * Replay email webhooks
1953
2124
  *
@@ -2077,10 +2248,34 @@ interface SendInput {
2077
2248
  waitTimeoutMs?: number;
2078
2249
  idempotencyKey?: string;
2079
2250
  }
2251
+ /**
2252
+ * Input shape for `client.reply(email, input)`.
2253
+ *
2254
+ * Can be a bare string (treated as `text`) or an object. The reply
2255
+ * operation calls the server's `/emails/{id}/reply` endpoint, which
2256
+ * derives recipients, subject (`Re: <parent>`), and threading headers
2257
+ * from the inbound row. The shape here is the small subset of fields
2258
+ * the customer can still control:
2259
+ *
2260
+ * - `text` / `html`: the reply body. At least one is required.
2261
+ * - `from`: optional override for the From header. Defaults server-
2262
+ * side to the address that received the inbound. Use to add a
2263
+ * display name (`"Acme Support" <agent@company.com>`) or to reply
2264
+ * from a different verified outbound address. The from-domain must
2265
+ * be a verified outbound domain for your org.
2266
+ * - `wait`: when true, wait for the first downstream SMTP delivery
2267
+ * outcome before resolving. Mirrors send-mail's `wait` semantics.
2268
+ *
2269
+ * `subject` is intentionally not accepted: a custom subject silently
2270
+ * breaks Gmail's threading because Gmail's Conversation View requires
2271
+ * both a References match and a normalized-subject match. Always
2272
+ * sends `Re: <parent>` with idempotent prefixing.
2273
+ */
2080
2274
  type ReplyInput = string | {
2081
- text: string;
2082
- subject?: string;
2275
+ text?: string;
2276
+ html?: string;
2083
2277
  from?: string;
2278
+ wait?: boolean;
2084
2279
  };
2085
2280
  interface ForwardInput {
2086
2281
  to: string;
@@ -2097,6 +2292,12 @@ interface SendResult {
2097
2292
  clientIdempotencyKey: string;
2098
2293
  requestId: string;
2099
2294
  contentHash: string;
2295
+ /**
2296
+ * True when the response replays a previously-recorded send keyed by
2297
+ * `clientIdempotencyKey` (same key, same canonical payload). False on
2298
+ * a fresh send and on gate-denied responses.
2299
+ */
2300
+ idempotentReplay: boolean;
2100
2301
  deliveryStatus?: SendMailResult["delivery_status"];
2101
2302
  smtpResponseCode?: number | null;
2102
2303
  smtpResponseText?: string;
@@ -2129,6 +2330,20 @@ declare class PrimitiveApiClient {
2129
2330
  type PrimitiveClientOptions = PrimitiveApiClientOptions;
2130
2331
  declare class PrimitiveClient extends PrimitiveApiClient {
2131
2332
  send(input: SendInput): Promise<SendResult>;
2333
+ /**
2334
+ * Reply to an inbound email.
2335
+ *
2336
+ * Calls `POST /emails/{id}/reply`. The server derives recipients
2337
+ * (Reply-To, then From, then sender), subject (`Re: <parent>` with
2338
+ * idempotent prefix), and threading headers (`In-Reply-To`,
2339
+ * `References`) from the stored inbound row. The customer controls
2340
+ * only the body, an optional `from` override, and the `wait` flag.
2341
+ *
2342
+ * Subject overrides are intentionally not supported: Gmail's
2343
+ * Conversation View needs both a References match and a normalized-
2344
+ * subject match to thread, so a custom subject silently breaks the
2345
+ * thread for half the recipient population.
2346
+ */
2132
2347
  reply(email: ReceivedEmail, input: ReplyInput): Promise<SendResult>;
2133
2348
  forward(email: ReceivedEmail, input: ForwardInput): Promise<SendResult>;
2134
2349
  }
@@ -2137,4 +2352,4 @@ declare function createPrimitiveClient(options?: PrimitiveClientOptions): Primit
2137
2352
  declare function client(options?: PrimitiveClientOptions): PrimitiveClient;
2138
2353
  declare const operations: typeof sdk_gen_d_exports;
2139
2354
  //#endregion
2140
- export { AddDomainResponses as $, ReplayDeliveryResponses as $n, VerifiedDomain as $r, GateDenial as $t, getWebhookSecret as A, ListDomainsResponse as An, UpdateAccountError as Ar, DeleteFilterError as At, testEndpoint as B, ListEndpointsResponse as Bn, UpdateDomainResponses as Br, DownloadAttachmentsErrors as Bt, deleteEndpoint as C, ListDeliveriesError as Cn, TestEndpointError as Cr, DeleteEmailResponses as Ct, getAccount as D, ListDomainsData as Dn, TestResult as Dr, DeleteEndpointResponse as Dt, downloadRawEmail as E, ListDeliveriesResponses as En, TestEndpointResponses as Er, DeleteEndpointErrors as Et, listFilters as F, ListEmailsResponse as Fn, UpdateDomainData as Fr, DeliverySummary as Ft, verifyDomain as G, ListFiltersErrors as Gn, UpdateEndpointResponse as Gr, DownloadRawEmailErrors as Gt, updateDomain as H, ListEnvelope as Hn, UpdateEndpointError as Hr, DownloadAttachmentsResponses as Ht, replayDelivery as I, ListEmailsResponses as In, UpdateDomainError as Ir, Domain as It, AddDomainData as J, PaginationMeta as Jn, UpdateFilterError as Jr, EmailDetail as Jt, Account as K, ListFiltersResponse as Kn, UpdateEndpointResponses as Kr, DownloadRawEmailResponse as Kt, replayEmailWebhooks as L, ListEndpointsData as Ln, UpdateDomainErrors as Lr, DomainVerifyResult as Lt, listDomains as M, ListEmailsData as Mn, UpdateAccountInput as Mr, DeleteFilterResponse as Mt, listEmails as N, ListEmailsError as Nn, UpdateAccountResponse as Nr, DeleteFilterResponses as Nt, getEmail as O, ListDomainsError as On, UnverifiedDomain as Or, DeleteEndpointResponses as Ot, listEndpoints as P, ListEmailsErrors as Pn, UpdateAccountResponses as Pr, DeliveryStatus as Pt, AddDomainResponse as Q, ReplayDeliveryResponse as Qn, UpdateFilterResponses as Qr, Filter as Qt, rotateWebhookSecret as R, ListEndpointsError as Rn, UpdateDomainInput as Rr, DownloadAttachmentsData as Rt, deleteEmail as S, ListDeliveriesData as Sn, TestEndpointData as Sr, DeleteEmailResponse as St, downloadAttachments as T, ListDeliveriesResponse as Tn, TestEndpointResponse as Tr, DeleteEndpointError as Tt, updateEndpoint as U, ListFiltersData as Un, UpdateEndpointErrors as Ur, DownloadRawEmailData as Ut, updateAccount as V, ListEndpointsResponses as Vn, UpdateEndpointData as Vr, DownloadAttachmentsResponse as Vt, updateFilter as W, ListFiltersError as Wn, UpdateEndpointInput as Wr, DownloadRawEmailError as Wt, AddDomainErrors as X, ReplayDeliveryError as Xn, UpdateFilterInput as Xr, Endpoint as Xt, AddDomainError as Y, ReplayDeliveryData as Yn, UpdateFilterErrors as Yr, EmailSummary as Yt, AddDomainInput as Z, ReplayDeliveryErrors as Zn, UpdateFilterResponse as Zr, ErrorResponse as Zt, Options as _, GetWebhookSecretError as _n, SendMailInput as _r, DeleteDomainResponse as _t, PrimitiveApiError as a, WebhookSecret as ai, GetAccountResponses as an, ReplayResult as ar, CreateEndpointResponse as at, createFilter as b, GetWebhookSecretResponses as bn, StorageStats as br, DeleteEmailError as bt, PrimitiveClientOptions as c, Config as ci, GetEmailErrors as cn, RotateWebhookSecretError as cr, CreateFilterError as ct, SendResult as d, RequestOptions as di, GetStorageStatsData as dn, RotateWebhookSecretResponses as dr, CreateFilterResponse as dt, VerifyDomainData as ei, GateFix as en, ReplayEmailWebhooksData as er, ClientOptions as et, SendThreadInput as f, RequestResult as fi, GetStorageStatsError as fn, SendEmailData as fr, CreateFilterResponses as ft, operations as g, GetWebhookSecretData as gn, SendEmailResponses as gr, DeleteDomainErrors as gt, createPrimitiveClient as h, GetStorageStatsResponses as hn, SendEmailResponse as hr, DeleteDomainError as ht, PrimitiveApiClientOptions as i, VerifyDomainResponses as ii, GetAccountResponse as in, ReplayEmailWebhooksResponses as ir, CreateEndpointInput as it, listDeliveries as j, ListDomainsResponses as jn, UpdateAccountErrors as jr, DeleteFilterErrors as jt, getStorageStats as k, ListDomainsErrors as kn, UpdateAccountData as kr, DeleteFilterData as kt, ReplyInput as l, CreateClientConfig as li, GetEmailResponse as ln, RotateWebhookSecretErrors as lr, CreateFilterErrors as lt, createPrimitiveApiClient as m, Auth as mi, GetStorageStatsResponse as mn, SendEmailErrors as mr, DeleteDomainData as mt, ForwardInput as n, VerifyDomainErrors as ni, GetAccountError as nn, ReplayEmailWebhooksErrors as nr, CreateEndpointError as nt, PrimitiveApiErrorDetails as o, Client as oi, GetEmailData as on, ResourceId as or, CreateEndpointResponses as ot, client as p, ResponseStyle as pi, GetStorageStatsErrors as pn, SendEmailError as pr, Cursor as pt, AccountUpdated as q, ListFiltersResponses as qn, UpdateFilterData as qr, DownloadRawEmailResponses as qt, PrimitiveApiClient as r, VerifyDomainResponse as ri, GetAccountErrors as rn, ReplayEmailWebhooksResponse as rr, CreateEndpointErrors as rt, PrimitiveClient as s, ClientOptions$1 as si, GetEmailError as sn, RotateWebhookSecretData as sr, CreateFilterData as st, DEFAULT_BASE_URL as t, VerifyDomainError as ti, GetAccountData as tn, ReplayEmailWebhooksError as tr, CreateEndpointData as tt, SendInput as u, Options$1 as ui, GetEmailResponses as un, RotateWebhookSecretResponse as ur, CreateFilterInput as ut, addDomain as v, GetWebhookSecretErrors as vn, SendMailResult as vr, DeleteDomainResponses as vt, deleteFilter as w, ListDeliveriesErrors as wn, TestEndpointErrors as wr, DeleteEndpointData as wt, deleteDomain as x, Limit as xn, SuccessEnvelope as xr, DeleteEmailErrors as xt, createEndpoint as y, GetWebhookSecretResponse as yn, SentEmailStatus as yr, DeleteEmailData as yt, sendEmail as z, ListEndpointsErrors as zn, UpdateDomainResponse as zr, DownloadAttachmentsError as zt };
2355
+ export { AddDomainResponse as $, ReplayDeliveryErrors as $n, UpdateEndpointResponses as $r, ErrorResponse as $t, getWebhookSecret as A, ListDomainsError as An, TestEndpointError as Ar, DeleteFilterData as At, sendEmail as B, ListEndpointsError as Bn, UpdateAccountResponse as Br, DownloadAttachmentsError as Bt, deleteEndpoint as C, Limit as Cn, SendEmailResponses as Cr, DeleteEmailResponse as Ct, getAccount as D, ListDeliveriesResponse as Dn, StorageStats as Dr, DeleteEndpointErrors as Dt, downloadRawEmail as E, ListDeliveriesErrors as En, SentEmailStatus as Er, DeleteEndpointError as Et, listFilters as F, ListEmailsError as Fn, UnverifiedDomain as Fr, DeliveryStatus as Ft, updateFilter as G, ListFiltersData as Gn, UpdateDomainInput as Gr, DownloadRawEmailError as Gt, updateAccount as H, ListEndpointsResponse as Hn, UpdateDomainData as Hr, DownloadAttachmentsResponse as Ht, replayDelivery as I, ListEmailsErrors as In, UpdateAccountData as Ir, DeliverySummary as It, AccountUpdated as J, ListFiltersResponse as Jn, UpdateEndpointData as Jr, DownloadRawEmailResponses as Jt, verifyDomain as K, ListFiltersError as Kn, UpdateDomainResponse as Kr, DownloadRawEmailErrors as Kt, replayEmailWebhooks as L, ListEmailsResponse as Ln, UpdateAccountError as Lr, Domain as Lt, listDomains as M, ListDomainsResponse as Mn, TestEndpointResponse as Mr, DeleteFilterErrors as Mt, listEmails as N, ListDomainsResponses as Nn, TestEndpointResponses as Nr, DeleteFilterResponse as Nt, getEmail as O, ListDeliveriesResponses as On, SuccessEnvelope as Or, DeleteEndpointResponse as Ot, listEndpoints as P, ListEmailsData as Pn, TestResult as Pr, DeleteFilterResponses as Pt, AddDomainInput as Q, ReplayDeliveryError as Qn, UpdateEndpointResponse as Qr, Endpoint as Qt, replyToEmail as R, ListEmailsResponses as Rn, UpdateAccountErrors as Rr, DomainVerifyResult as Rt, deleteEmail as S, GetWebhookSecretResponses as Sn, SendEmailResponse as Sr, DeleteEmailErrors as St, downloadAttachments as T, ListDeliveriesError as Tn, SendMailResult as Tr, DeleteEndpointData as Tt, updateDomain as U, ListEndpointsResponses as Un, UpdateDomainError as Ur, DownloadAttachmentsResponses as Ut, testEndpoint as V, ListEndpointsErrors as Vn, UpdateAccountResponses as Vr, DownloadAttachmentsErrors as Vt, updateEndpoint as W, ListEnvelope as Wn, UpdateDomainErrors as Wr, DownloadRawEmailData as Wt, AddDomainError as X, PaginationMeta as Xn, UpdateEndpointErrors as Xr, EmailDetailReply as Xt, AddDomainData as Y, ListFiltersResponses as Yn, UpdateEndpointError as Yr, EmailDetail as Yt, AddDomainErrors as Z, ReplayDeliveryData as Zn, UpdateEndpointInput as Zr, EmailSummary as Zt, Options as _, Options$1 as _i, GetStorageStatsResponses as _n, RotateWebhookSecretResponse as _r, DeleteDomainErrors as _t, PrimitiveApiError as a, UpdateFilterResponses as ai, GetAccountErrors as an, ReplayEmailWebhooksResponse as ar, CreateEndpointInput as at, createFilter as b, ResponseStyle as bi, GetWebhookSecretErrors as bn, SendEmailError as br, DeleteEmailData as bt, PrimitiveClientOptions as c, VerifyDomainError as ci, GetEmailData as cn, ReplyToEmailData as cr, CreateFilterData as ct, SendResult as d, VerifyDomainResponses as di, GetEmailResponse as dn, ReplyToEmailResponse as dr, CreateFilterInput as dt, UpdateFilterData as ei, Filter as en, ReplayDeliveryResponse as er, AddDomainResponses as et, SendThreadInput as f, WebhookSecret as fi, GetEmailResponses as fn, ReplyToEmailResponses as fr, CreateFilterResponse as ft, operations as g, CreateClientConfig as gi, GetStorageStatsResponse as gn, RotateWebhookSecretErrors as gr, DeleteDomainError as gt, createPrimitiveClient as h, Config as hi, GetStorageStatsErrors as hn, RotateWebhookSecretError as hr, DeleteDomainData as ht, PrimitiveApiClientOptions as i, UpdateFilterResponse as ii, GetAccountError as in, ReplayEmailWebhooksErrors as ir, CreateEndpointErrors as it, listDeliveries as j, ListDomainsErrors as jn, TestEndpointErrors as jr, DeleteFilterError as jt, getStorageStats as k, ListDomainsData as kn, TestEndpointData as kr, DeleteEndpointResponses as kt, ReplyInput as l, VerifyDomainErrors as li, GetEmailError as ln, ReplyToEmailError as lr, CreateFilterError as lt, createPrimitiveApiClient as m, ClientOptions$1 as mi, GetStorageStatsError as mn, RotateWebhookSecretData as mr, Cursor as mt, ForwardInput as n, UpdateFilterErrors as ni, GateFix as nn, ReplayEmailWebhooksData as nr, CreateEndpointData as nt, PrimitiveApiErrorDetails as o, VerifiedDomain as oi, GetAccountResponse as on, ReplayEmailWebhooksResponses as or, CreateEndpointResponse as ot, client as p, Client as pi, GetStorageStatsData as pn, ResourceId as pr, CreateFilterResponses as pt, Account as q, ListFiltersErrors as qn, UpdateDomainResponses as qr, DownloadRawEmailResponse as qt, PrimitiveApiClient as r, UpdateFilterInput as ri, GetAccountData as rn, ReplayEmailWebhooksError as rr, CreateEndpointError as rt, PrimitiveClient as s, VerifyDomainData as si, GetAccountResponses as sn, ReplayResult as sr, CreateEndpointResponses as st, DEFAULT_BASE_URL as t, UpdateFilterError as ti, GateDenial as tn, ReplayDeliveryResponses as tr, ClientOptions as tt, SendInput as u, VerifyDomainResponse as ui, GetEmailErrors as un, ReplyToEmailErrors as ur, CreateFilterErrors as ut, addDomain as v, RequestOptions as vi, GetWebhookSecretData as vn, RotateWebhookSecretResponses as vr, DeleteDomainResponse as vt, deleteFilter as w, ListDeliveriesData as wn, SendMailInput as wr, DeleteEmailResponses as wt, deleteDomain as x, Auth as xi, GetWebhookSecretResponse as xn, SendEmailErrors as xr, DeleteEmailError as xt, createEndpoint as y, RequestResult as yi, GetWebhookSecretError as yn, SendEmailData as yr, DeleteDomainResponses as yt, rotateWebhookSecret as z, ListEndpointsData as zn, UpdateAccountInput as zr, DownloadAttachmentsData as zt };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { A as UnknownEvent, C as ParsedDataFailed, D as RawContentDownloadOnly, E as RawContent, M as WebhookAttachment, N as WebhookEvent, O as RawContentInline, S as ParsedDataComplete, T as ParsedStatus, _ as ForwardResultInline, a as DmarcPolicy, b as KnownWebhookEvent, c as EmailAnalysis, d as EventType, f as ForwardAnalysis, g as ForwardResultAttachmentSkipped, h as ForwardResultAttachmentAnalyzed, i as DkimSignature, j as ValidateEmailAuthResult, k as SpfResult, l as EmailAuth, m as ForwardResult, n as AuthVerdict, o as DmarcResult, p as ForwardOriginalSender, r as DkimResult, s as EmailAddress, t as AuthConfidence, u as EmailReceivedEvent, v as ForwardVerdict, w as ParsedError, x as ParsedData, y as ForwardVerification } from "./types-9vXGZjPd.js";
2
2
  import { a as buildReplySubject, c as parseHeaderAddress, i as buildForwardSubject, n as ReceivedEmailAddress, o as formatAddress, r as ReceivedEmailThread, s as normalizeReceivedEmail, t as ReceivedEmail } from "./received-email-DNjpq_Wt.js";
3
- import { a as PrimitiveApiError, c as PrimitiveClientOptions, d as SendResult, f as SendThreadInput, h as createPrimitiveClient, l as ReplyInput, n as ForwardInput, p as client, s as PrimitiveClient, u as SendInput } from "./index-DVow4Fjd.js";
3
+ import { a as PrimitiveApiError, c as PrimitiveClientOptions, d as SendResult, f as SendThreadInput, h as createPrimitiveClient, l as ReplyInput, n as ForwardInput, p as client, s as PrimitiveClient, u as SendInput } from "./index-K4KbjppU.js";
4
4
  import { A as VerifyOptions, B as PAYLOAD_ERRORS, C as signStandardWebhooksPayload, D as PRIMITIVE_CONFIRMED_HEADER, E as LEGACY_SIGNATURE_HEADER, F as VerifyDownloadTokenResult, G as VERIFICATION_ERRORS, H as RAW_EMAIL_ERRORS, I as generateDownloadToken, J as WebhookPayloadErrorCode, K as WebhookErrorCode, L as verifyDownloadToken, M as verifyWebhookSignature, N as GenerateDownloadTokenOptions, O as PRIMITIVE_SIGNATURE_HEADER, P as VerifyDownloadTokenOptions, Q as WebhookVerificationErrorCode, R as safeValidateEmailReceivedEvent, S as StandardWebhooksVerifyOptions, T as LEGACY_CONFIRMED_HEADER, U as RawEmailDecodeError, V as PrimitiveWebhookError, W as RawEmailDecodeErrorCode, X as WebhookValidationErrorCode, Y as WebhookValidationError, Z as WebhookVerificationError, _ as emailReceivedEventJsonSchema, a as confirmedHeaders, b as STANDARD_WEBHOOK_TIMESTAMP_HEADER, c as handleWebhook, d as isRawIncluded, f as parseWebhookEvent, g as validateEmailAuth, h as WEBHOOK_VERSION, i as WebhookHeaders, j as signWebhookPayload, k as SignResult, l as isDownloadExpired, m as verifyRawEmailDownload, n as HandleWebhookOptions, o as decodeRawEmail, p as receive, q as WebhookPayloadError, r as ReceiveRequestOptions, s as getDownloadTimeRemaining, t as DecodeRawEmailOptions, u as isEmailReceivedEvent, v as STANDARD_WEBHOOK_ID_HEADER, w as verifyStandardWebhooksSignature, x as StandardWebhooksSignResult, y as STANDARD_WEBHOOK_SIGNATURE_HEADER, z as validateEmailReceivedEvent } from "./index-CbEivn3S.js";
5
5
 
6
6
  //#region src/index.d.ts
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as parseHeaderAddress, i as normalizeReceivedEmail, n as buildReplySubject, r as formatAddress, t as buildForwardSubject } from "./received-email-D6tKtWwW.js";
2
- import { a as client, i as PrimitiveClient, r as PrimitiveApiError, s as createPrimitiveClient } from "./api-COSr-Fqm.js";
2
+ import { a as client, i as PrimitiveClient, r as PrimitiveApiError, s as createPrimitiveClient } from "./api-CLLpjjWy.js";
3
3
  import { A as PRIMITIVE_CONFIRMED_HEADER, B as RAW_EMAIL_ERRORS, C as STANDARD_WEBHOOK_ID_HEADER, D as verifyStandardWebhooksSignature, E as signStandardWebhooksPayload, F as verifyDownloadToken, G as WebhookVerificationError, H as VERIFICATION_ERRORS, I as safeValidateEmailReceivedEvent, L as validateEmailReceivedEvent, M as signWebhookPayload, N as verifyWebhookSignature, O as LEGACY_CONFIRMED_HEADER, P as generateDownloadToken, R as PAYLOAD_ERRORS, S as emailReceivedEventJsonSchema, T as STANDARD_WEBHOOK_TIMESTAMP_HEADER, U as WebhookPayloadError, V as RawEmailDecodeError, W as WebhookValidationError, _ as DmarcResult, a as isDownloadExpired, b as ParsedStatus, c as parseWebhookEvent, d as WEBHOOK_VERSION, f as validateEmailAuth, g as DmarcPolicy, h as DkimResult, i as handleWebhook, j as PRIMITIVE_SIGNATURE_HEADER, k as LEGACY_SIGNATURE_HEADER, l as receive, m as AuthVerdict, n as decodeRawEmail, o as isEmailReceivedEvent, p as AuthConfidence, r as getDownloadTimeRemaining, s as isRawIncluded, t as confirmedHeaders, u as verifyRawEmailDownload, v as EventType, w as STANDARD_WEBHOOK_SIGNATURE_HEADER, x as SpfResult, y as ForwardVerdict, z as PrimitiveWebhookError } from "./webhook-zkN4wUTs.js";
4
4
  //#region src/index.ts
5
5
  const primitive = {
@@ -842,6 +842,96 @@ export const openapiDocument = {
842
842
  }
843
843
  }
844
844
  },
845
+ "/emails/{id}/reply": {
846
+ "parameters": [
847
+ {
848
+ "$ref": "#/components/parameters/ResourceId"
849
+ }
850
+ ],
851
+ "post": {
852
+ "operationId": "replyToEmail",
853
+ "summary": "Reply to an inbound email",
854
+ "description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional `wait` flag; passing any header or recipient\noverride is rejected by the schema (`additionalProperties:\nfalse`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n",
855
+ "tags": [
856
+ "Sending"
857
+ ],
858
+ "requestBody": {
859
+ "required": true,
860
+ "content": {
861
+ "application/json": {
862
+ "schema": {
863
+ "$ref": "#/components/schemas/ReplyInput"
864
+ }
865
+ }
866
+ }
867
+ },
868
+ "responses": {
869
+ "200": {
870
+ "description": "Outbound relay result",
871
+ "content": {
872
+ "application/json": {
873
+ "schema": {
874
+ "allOf": [
875
+ {
876
+ "$ref": "#/components/schemas/SuccessEnvelope"
877
+ },
878
+ {
879
+ "type": "object",
880
+ "properties": {
881
+ "data": {
882
+ "$ref": "#/components/schemas/SendMailResult"
883
+ }
884
+ }
885
+ }
886
+ ]
887
+ }
888
+ }
889
+ }
890
+ },
891
+ "400": {
892
+ "$ref": "#/components/responses/ValidationError"
893
+ },
894
+ "401": {
895
+ "$ref": "#/components/responses/Unauthorized"
896
+ },
897
+ "403": {
898
+ "$ref": "#/components/responses/Forbidden"
899
+ },
900
+ "404": {
901
+ "$ref": "#/components/responses/NotFound"
902
+ },
903
+ "422": {
904
+ "description": "Inbound is not repliable: the row exists but lacks a\n`message_id` (no thread anchor) or a `recipient` (cannot\nderive the From address).\n",
905
+ "content": {
906
+ "application/json": {
907
+ "schema": {
908
+ "$ref": "#/components/schemas/ErrorResponse"
909
+ },
910
+ "example": {
911
+ "success": false,
912
+ "error": {
913
+ "code": "inbound_not_repliable",
914
+ "message": "inbound has no Message-ID; cannot anchor a reply thread"
915
+ }
916
+ }
917
+ }
918
+ }
919
+ },
920
+ "429": {
921
+ "$ref": "#/components/responses/RateLimited"
922
+ },
923
+ "500": {
924
+ "$ref": "#/components/responses/InternalError"
925
+ },
926
+ "502": {
927
+ "$ref": "#/components/responses/BadGateway"
928
+ },
929
+ "503": {
930
+ "$ref": "#/components/responses/ServiceUnavailable"
931
+ }
932
+ }
933
+ }
934
+ },
845
935
  "/emails/{id}/replay": {
846
936
  "parameters": [
847
937
  {
@@ -1819,7 +1909,8 @@ export const openapiDocument = {
1819
1909
  "outbound_key_invalid",
1820
1910
  "outbound_capacity_exhausted",
1821
1911
  "outbound_response_malformed",
1822
- "outbound_relay_failed"
1912
+ "outbound_relay_failed",
1913
+ "inbound_not_repliable"
1823
1914
  ]
1824
1915
  },
1825
1916
  "message": {
@@ -2443,6 +2534,20 @@ export const openapiDocument = {
2443
2534
  "null"
2444
2535
  ]
2445
2536
  },
2537
+ "body_text": {
2538
+ "type": [
2539
+ "string",
2540
+ "null"
2541
+ ],
2542
+ "description": "Plain-text body parsed from the inbound MIME, matching the `email.parsed.body_text` field on the webhook payload. Null when the message had no text part or parsing failed."
2543
+ },
2544
+ "body_html": {
2545
+ "type": [
2546
+ "string",
2547
+ "null"
2548
+ ],
2549
+ "description": "HTML body parsed from the inbound MIME, matching the `email.parsed.body_html` field on the webhook payload. Null when the message had no HTML part or parsing failed."
2550
+ },
2446
2551
  "status": {
2447
2552
  "type": "string",
2448
2553
  "enum": [
@@ -2577,6 +2682,17 @@ export const openapiDocument = {
2577
2682
  "to_email": {
2578
2683
  "type": "string",
2579
2684
  "description": "Parsed to address (same as recipient)"
2685
+ },
2686
+ "from_known_address": {
2687
+ "type": "boolean",
2688
+ "description": "True when the inbound's sender address has a matching grant\nin the org's known-send-addresses list. Advisory: a true\nvalue does not by itself guarantee that a reply will be\naccepted by send-mail's gates; the per-send check at send\ntime remains authoritative.\n"
2689
+ },
2690
+ "replies": {
2691
+ "type": "array",
2692
+ "description": "Sent emails recorded as replies to this inbound, in send\norder (ascending). Populated when a customer's send-mail\nrequest carries an `in_reply_to` Message-ID that matches\nthis inbound's `message_id` in the same org. Includes\nattempts that were gate-denied, so the array reflects every\nrecorded reply attempt regardless of outcome.\n",
2693
+ "items": {
2694
+ "$ref": "#/components/schemas/EmailDetailReply"
2695
+ }
2580
2696
  }
2581
2697
  },
2582
2698
  "required": [
@@ -2589,7 +2705,48 @@ export const openapiDocument = {
2589
2705
  "received_at",
2590
2706
  "webhook_attempt_count",
2591
2707
  "from_email",
2592
- "to_email"
2708
+ "to_email",
2709
+ "replies"
2710
+ ]
2711
+ },
2712
+ "EmailDetailReply": {
2713
+ "type": "object",
2714
+ "properties": {
2715
+ "id": {
2716
+ "type": "string",
2717
+ "format": "uuid",
2718
+ "description": "Sent-email row id."
2719
+ },
2720
+ "status": {
2721
+ "$ref": "#/components/schemas/SentEmailStatus"
2722
+ },
2723
+ "to_address": {
2724
+ "type": "string",
2725
+ "description": "Recipient address as recorded on the sent_emails row."
2726
+ },
2727
+ "subject": {
2728
+ "type": [
2729
+ "string",
2730
+ "null"
2731
+ ]
2732
+ },
2733
+ "created_at": {
2734
+ "type": "string",
2735
+ "format": "date-time"
2736
+ },
2737
+ "queue_id": {
2738
+ "type": [
2739
+ "string",
2740
+ "null"
2741
+ ],
2742
+ "description": "Outbound relay queue identifier when available."
2743
+ }
2744
+ },
2745
+ "required": [
2746
+ "id",
2747
+ "status",
2748
+ "to_address",
2749
+ "created_at"
2593
2750
  ]
2594
2751
  },
2595
2752
  "SendMailInput": {
@@ -2679,6 +2836,31 @@ export const openapiDocument = {
2679
2836
  "wait_timeout"
2680
2837
  ]
2681
2838
  },
2839
+ "ReplyInput": {
2840
+ "type": "object",
2841
+ "additionalProperties": false,
2842
+ "description": "Body shape for `/emails/{id}/reply`. Intentionally narrow:\nrecipients (`to`), subject, and threading headers\n(`in_reply_to`, `references`) are derived server-side from\nthe inbound row referenced by the path id and are rejected by\n`additionalProperties` if passed (returns 400).\n\n`from` IS allowed because of legitimate use cases (display-name\naddition, replying from a different verified outbound address,\nmulti-team triage). Send-mail's per-send `canSendFrom` gate\nvalidates the from-domain regardless, so the override carries\nno extra privilege.\n",
2843
+ "properties": {
2844
+ "body_text": {
2845
+ "type": "string",
2846
+ "description": "Plain-text reply body. At least one of body_text or body_html is required. The combined UTF-8 byte length of body_text and body_html must be at most 262144 bytes (same cap as send-mail)."
2847
+ },
2848
+ "body_html": {
2849
+ "type": "string",
2850
+ "description": "HTML reply body. At least one of body_text or body_html is required."
2851
+ },
2852
+ "from": {
2853
+ "type": "string",
2854
+ "minLength": 3,
2855
+ "maxLength": 998,
2856
+ "description": "Optional override for the reply's From header. Defaults to\nthe inbound's recipient. Use to add a display name (`\"Acme\nSupport\" <agent@company.com>`) or to reply from a different\nverified outbound address (e.g. multi-team routing where\nsupport@ triages to billing@). The from-domain must be a\nverified outbound domain for your org, same as send-mail.\n"
2857
+ },
2858
+ "wait": {
2859
+ "type": "boolean",
2860
+ "description": "When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics."
2861
+ }
2862
+ }
2863
+ },
2682
2864
  "SendMailResult": {
2683
2865
  "type": "object",
2684
2866
  "properties": {
@@ -2735,6 +2917,10 @@ export const openapiDocument = {
2735
2917
  "smtp_response_text": {
2736
2918
  "type": "string",
2737
2919
  "description": "SMTP response text from the first downstream delivery outcome when wait is true."
2920
+ },
2921
+ "idempotent_replay": {
2922
+ "type": "boolean",
2923
+ "description": "True when the response replays a previously-recorded send\nkeyed by `client_idempotency_key` (same key, same canonical\npayload). False on a fresh send and on gate-denied\nresponses. Lets callers branch on cache state without\ndiffing fields.\n"
2738
2924
  }
2739
2925
  },
2740
2926
  "required": [
@@ -2745,7 +2931,8 @@ export const openapiDocument = {
2745
2931
  "rejected",
2746
2932
  "client_idempotency_key",
2747
2933
  "request_id",
2748
- "content_hash"
2934
+ "content_hash",
2935
+ "idempotent_replay"
2749
2936
  ]
2750
2937
  },
2751
2938
  "Endpoint": {
@@ -752,6 +752,55 @@ export const operationManifest = [
752
752
  "tag": "Filters",
753
753
  "tagCommand": "filters"
754
754
  },
755
+ {
756
+ "binaryResponse": false,
757
+ "bodyRequired": true,
758
+ "command": "reply-to-email",
759
+ "description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional `wait` flag; passing any header or recipient\noverride is rejected by the schema (`additionalProperties:\nfalse`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n",
760
+ "hasJsonBody": true,
761
+ "method": "POST",
762
+ "operationId": "replyToEmail",
763
+ "path": "/emails/{id}/reply",
764
+ "pathParams": [
765
+ {
766
+ "description": "Resource UUID",
767
+ "enum": null,
768
+ "name": "id",
769
+ "required": true,
770
+ "type": "string"
771
+ }
772
+ ],
773
+ "queryParams": [],
774
+ "requestSchema": {
775
+ "type": "object",
776
+ "additionalProperties": false,
777
+ "description": "Body shape for `/emails/{id}/reply`. Intentionally narrow:\nrecipients (`to`), subject, and threading headers\n(`in_reply_to`, `references`) are derived server-side from\nthe inbound row referenced by the path id and are rejected by\n`additionalProperties` if passed (returns 400).\n\n`from` IS allowed because of legitimate use cases (display-name\naddition, replying from a different verified outbound address,\nmulti-team triage). Send-mail's per-send `canSendFrom` gate\nvalidates the from-domain regardless, so the override carries\nno extra privilege.\n",
778
+ "properties": {
779
+ "body_text": {
780
+ "type": "string",
781
+ "description": "Plain-text reply body. At least one of body_text or body_html is required. The combined UTF-8 byte length of body_text and body_html must be at most 262144 bytes (same cap as send-mail)."
782
+ },
783
+ "body_html": {
784
+ "type": "string",
785
+ "description": "HTML reply body. At least one of body_text or body_html is required."
786
+ },
787
+ "from": {
788
+ "type": "string",
789
+ "minLength": 3,
790
+ "maxLength": 998,
791
+ "description": "Optional override for the reply's From header. Defaults to\nthe inbound's recipient. Use to add a display name (`\"Acme\nSupport\" <agent@company.com>`) or to reply from a different\nverified outbound address (e.g. multi-team routing where\nsupport@ triages to billing@). The from-domain must be a\nverified outbound domain for your org, same as send-mail.\n"
792
+ },
793
+ "wait": {
794
+ "type": "boolean",
795
+ "description": "When true, wait for the first downstream SMTP delivery outcome before returning, mirroring the send-mail `wait` semantics."
796
+ }
797
+ }
798
+ },
799
+ "sdkName": "replyToEmail",
800
+ "summary": "Reply to an inbound email",
801
+ "tag": "Sending",
802
+ "tagCommand": "sending"
803
+ },
755
804
  {
756
805
  "binaryResponse": false,
757
806
  "bodyRequired": true,
@@ -1136,6 +1136,60 @@
1136
1136
  "summary": "Update a filter rule",
1137
1137
  "enableJsonFlag": false
1138
1138
  },
1139
+ "sending:reply-to-email": {
1140
+ "aliases": [],
1141
+ "args": {},
1142
+ "description": "Sends an outbound reply to the inbound email identified by `id`.\nThreading headers (`In-Reply-To`, `References`), recipient\nderivation (Reply-To, then From, then bare sender), and the\n`Re:` subject prefix are all derived server-side from the\nstored inbound row. The request body carries only the message\nbody and optional `wait` flag; passing any header or recipient\noverride is rejected by the schema (`additionalProperties:\nfalse`).\n\nForwards through the same gates as `/send-mail`: the response\nstatus, error envelope, and `idempotent_replay` flag mirror\nthe send-mail contract verbatim.\n\n\nBody fields (JSON --body):\n body_html string HTML reply body. At least one of body_text or body_html is required.\n body_text string Plain-text reply body. At least one of body_text or body_html is required. ...\n from string Optional override for the reply's From header. Defaults to\n wait boolean When true, wait for the first downstream SMTP delivery outcome before retur...\n(* = required)",
1143
+ "flags": {
1144
+ "api-key": {
1145
+ "description": "Primitive API key (defaults to PRIMITIVE_API_KEY)",
1146
+ "env": "PRIMITIVE_API_KEY",
1147
+ "name": "api-key",
1148
+ "hasDynamicHelp": false,
1149
+ "multiple": false,
1150
+ "type": "option"
1151
+ },
1152
+ "base-url": {
1153
+ "description": "API base URL (defaults to PRIMITIVE_API_URL or production)",
1154
+ "env": "PRIMITIVE_API_URL",
1155
+ "name": "base-url",
1156
+ "hasDynamicHelp": false,
1157
+ "multiple": false,
1158
+ "type": "option"
1159
+ },
1160
+ "id": {
1161
+ "description": "Resource UUID",
1162
+ "name": "id",
1163
+ "required": true,
1164
+ "hasDynamicHelp": false,
1165
+ "multiple": false,
1166
+ "type": "option"
1167
+ },
1168
+ "body": {
1169
+ "description": "JSON request body",
1170
+ "name": "body",
1171
+ "hasDynamicHelp": false,
1172
+ "multiple": false,
1173
+ "type": "option"
1174
+ },
1175
+ "body-file": {
1176
+ "description": "Path to a JSON file used as the request body",
1177
+ "name": "body-file",
1178
+ "hasDynamicHelp": false,
1179
+ "multiple": false,
1180
+ "type": "option"
1181
+ }
1182
+ },
1183
+ "hasDynamicHelp": false,
1184
+ "hiddenAliases": [],
1185
+ "id": "sending:reply-to-email",
1186
+ "pluginAlias": "@primitivedotdev/sdk",
1187
+ "pluginName": "@primitivedotdev/sdk",
1188
+ "pluginType": "core",
1189
+ "strict": true,
1190
+ "summary": "Reply to an inbound email",
1191
+ "enableJsonFlag": false
1192
+ },
1139
1193
  "sending:send-email": {
1140
1194
  "aliases": [],
1141
1195
  "args": {},
@@ -1309,5 +1363,5 @@
1309
1363
  "enableJsonFlag": false
1310
1364
  }
1311
1365
  },
1312
- "version": "0.9.0"
1366
+ "version": "0.10.0"
1313
1367
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primitivedotdev/sdk",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Official Primitive Node.js SDK — webhook, api, openapi, contract, and parser modules",
5
5
  "type": "module",
6
6
  "module": "./dist/index.js",