@primitivedotdev/sdk 0.15.0 → 0.17.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/dist/api/generated/index.js +1 -1
- package/dist/api/generated/sdk.gen.js +71 -10
- package/dist/api/index.d.ts +2 -2
- package/dist/{api-DpATn7LQ.js → api-DrAZhxS-.js} +76 -11
- package/dist/{index-DEY4h3MZ.d.ts → index-CHWqMBs6.d.ts} +166 -14
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/oclif/api-command.js +2 -2
- package/dist/oclif/commands/emails-latest.js +31 -7
- package/dist/openapi/openapi.generated.js +84 -5
- package/dist/openapi/operations.generated.js +49 -5
- package/oclif.manifest.json +46 -5
- package/package.json +1 -1
|
@@ -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, getSendPermissions, getSentEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, listSentEmails, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain } from './sdk.gen.js';
|
|
2
|
+
export { addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, discardEmailContent, downloadAttachments, downloadRawEmail, getAccount, getEmail, getSendPermissions, getSentEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, listSentEmails, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain } from './sdk.gen.js';
|
|
@@ -31,8 +31,25 @@ export const getStorageStats = (options) => (options?.client ?? client).get({
|
|
|
31
31
|
/**
|
|
32
32
|
* Get webhook signing secret
|
|
33
33
|
*
|
|
34
|
-
* Returns the webhook signing secret for your account. If no
|
|
35
|
-
* exists yet, one is generated automatically on first
|
|
34
|
+
* Returns the webhook signing secret for your account. If no
|
|
35
|
+
* secret exists yet, one is generated automatically on first
|
|
36
|
+
* access.
|
|
37
|
+
*
|
|
38
|
+
* Signing is account-scoped, not per-endpoint. Every webhook
|
|
39
|
+
* delivery from any of your registered endpoints is signed
|
|
40
|
+
* with this single secret. Rotate via
|
|
41
|
+
* `POST /account/webhook-secret/rotate`.
|
|
42
|
+
*
|
|
43
|
+
* **Secret format**: the returned string looks base64-shaped
|
|
44
|
+
* (e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`) but is NOT base64.
|
|
45
|
+
* Use it AS-IS as a UTF-8 string when computing HMAC over a
|
|
46
|
+
* delivery body. Base64-decoding before HMAC will silently
|
|
47
|
+
* produce mismatched signatures.
|
|
48
|
+
*
|
|
49
|
+
* See the API-level "Webhook signing" section for the full
|
|
50
|
+
* wire format (header name, signed string shape, hash algo,
|
|
51
|
+
* tolerance) including a language-agnostic verification
|
|
52
|
+
* recipe.
|
|
36
53
|
*
|
|
37
54
|
*/
|
|
38
55
|
export const getWebhookSecret = (options) => (options?.client ?? client).get({
|
|
@@ -125,12 +142,20 @@ export const verifyDomain = (options) => (options.client ?? client).post({
|
|
|
125
142
|
* List inbound emails
|
|
126
143
|
*
|
|
127
144
|
* Returns a paginated list of INBOUND emails received at your
|
|
128
|
-
* verified domains. Outbound messages sent via /send-mail are
|
|
129
|
-
* included; this endpoint is the inbox view, not a
|
|
130
|
-
* send/receive history.
|
|
145
|
+
* verified domains. Outbound messages sent via /send-mail are
|
|
146
|
+
* not included; this endpoint is the inbox view, not a
|
|
147
|
+
* unified send/receive history.
|
|
131
148
|
*
|
|
132
|
-
* Supports filtering by domain, status, date range, and
|
|
133
|
-
* search across subject, sender, and recipient
|
|
149
|
+
* Supports filtering by domain, status, date range, and
|
|
150
|
+
* free-text search across subject, sender, and recipient
|
|
151
|
+
* fields.
|
|
152
|
+
*
|
|
153
|
+
* For a compact text-table summary of the most recent N
|
|
154
|
+
* inbounds (no filters, no cursor pagination), the CLI ships
|
|
155
|
+
* `primitive emails:latest` as a one-line-per-email shortcut.
|
|
156
|
+
* It's TTY-aware so id columns are full UUIDs when piped, and
|
|
157
|
+
* a `--json` flag returns the same envelope this endpoint
|
|
158
|
+
* does. Use whichever fits the call site.
|
|
134
159
|
*
|
|
135
160
|
*/
|
|
136
161
|
export const listEmails = (options) => (options?.client ?? client).get({
|
|
@@ -252,6 +277,29 @@ export const replayEmailWebhooks = (options) => (options.client ?? client).post(
|
|
|
252
277
|
url: '/emails/{id}/replay',
|
|
253
278
|
...options
|
|
254
279
|
});
|
|
280
|
+
/**
|
|
281
|
+
* Discard email content
|
|
282
|
+
*
|
|
283
|
+
* Permanently deletes the email's raw bytes, parsed body (text + HTML),
|
|
284
|
+
* and attachments while preserving metadata (sender, recipient,
|
|
285
|
+
* subject, timestamps, hashes, attachment manifest) for audit logs.
|
|
286
|
+
* Idempotent: a second call returns success with
|
|
287
|
+
* `already_discarded: true` and does no work.
|
|
288
|
+
*
|
|
289
|
+
* **Gated** on the customer's discard-content opt-in (managed in the
|
|
290
|
+
* dashboard at Settings > Webhooks). When the toggle is off, this
|
|
291
|
+
* endpoint returns `403` with code `discard_not_enabled` and a
|
|
292
|
+
* message pointing the human at the dashboard. There is intentionally
|
|
293
|
+
* no API to flip this toggle — opting in to a destructive,
|
|
294
|
+
* non-reversible operation must be a deliberate human click in the
|
|
295
|
+
* UI.
|
|
296
|
+
*
|
|
297
|
+
*/
|
|
298
|
+
export const discardEmailContent = (options) => (options.client ?? client).post({
|
|
299
|
+
security: [{ scheme: 'bearer', type: 'http' }],
|
|
300
|
+
url: '/emails/{id}/discard-content',
|
|
301
|
+
...options
|
|
302
|
+
});
|
|
255
303
|
/**
|
|
256
304
|
* List webhook endpoints
|
|
257
305
|
*
|
|
@@ -265,9 +313,22 @@ export const listEndpoints = (options) => (options?.client ?? client).get({
|
|
|
265
313
|
/**
|
|
266
314
|
* Create a webhook endpoint
|
|
267
315
|
*
|
|
268
|
-
* Creates a new webhook endpoint. If a deactivated endpoint
|
|
269
|
-
* same URL and domain exists, it is reactivated
|
|
270
|
-
* Subject to plan limits on the number of active
|
|
316
|
+
* Creates a new webhook endpoint. If a deactivated endpoint
|
|
317
|
+
* with the same URL and domain exists, it is reactivated
|
|
318
|
+
* instead. Subject to plan limits on the number of active
|
|
319
|
+
* endpoints.
|
|
320
|
+
*
|
|
321
|
+
* **Signing is account-scoped, not per-endpoint.** This call
|
|
322
|
+
* does not return any signing material; every endpoint on the
|
|
323
|
+
* account uses the same webhook secret, fetched via
|
|
324
|
+
* `GET /account/webhook-secret`. See the API-level "Webhook
|
|
325
|
+
* signing" section for the full wire format (header name,
|
|
326
|
+
* signed string, hash algo, secret format, tolerance) and a
|
|
327
|
+
* language-agnostic verification recipe.
|
|
328
|
+
*
|
|
329
|
+
* After creating the endpoint, fire a test delivery against
|
|
330
|
+
* it via `POST /endpoints/{id}/test` to confirm your verifier
|
|
331
|
+
* accepts the signature.
|
|
271
332
|
*
|
|
272
333
|
*/
|
|
273
334
|
export const createEndpoint = (options) => (options.client ?? client).post({
|
package/dist/api/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as
|
|
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, EmailStatus, EmailSummary, EmailWebhookStatus, Endpoint, ErrorResponse, Filter, ForwardInput, GateDenial, GateFix, GetAccountData, GetAccountError, GetAccountErrors, GetAccountResponse, GetAccountResponses, GetEmailData, GetEmailError, GetEmailErrors, GetEmailResponse, GetEmailResponses, GetSendPermissionsData, GetSendPermissionsError, GetSendPermissionsErrors, GetSendPermissionsResponse, GetSendPermissionsResponses, GetSentEmailData, GetSentEmailError, GetSentEmailErrors, GetSentEmailResponse, GetSentEmailResponses, 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, ListSentEmailsData, ListSentEmailsError, ListSentEmailsErrors, ListSentEmailsResponse, ListSentEmailsResponses, 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, SendPermissionAddress, SendPermissionAnyRecipient, SendPermissionManagedZone, SendPermissionRule, SendPermissionYourDomain, SendPermissionsMeta, SendResult, SendThreadInput, SentEmailDetail, SentEmailStatus, SentEmailSummary, 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, getSendPermissions, getSentEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, listSentEmails, operations, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
|
|
1
|
+
import { $ as AddDomainData, $i as RequestOptions, $n as ListDomainsErrors, $r as SendPermissionAddress, $t as DownloadAttachmentsResponses, A as getSendPermissions, Ai as UpdateEndpointError, An as GetSentEmailData, Ar as ReplayEmailWebhooksError, At as DeleteEndpointError, B as replayDelivery, Bi as UpdateFilterResponses, Bn as GetWebhookSecretData, Br as ResourceId, Bt as DeliverySummary, C as deleteEndpoint, Ci as UpdateDomainData, Cn as GetEmailResponse, Cr as PaginationMeta, Ct as DeleteDomainResponses, D as downloadRawEmail, Di as UpdateDomainResponse, Dn as GetSendPermissionsErrors, Dr as ReplayDeliveryResponse, Dt as DeleteEmailResponse, E as downloadAttachments, Ei as UpdateDomainInput, En as GetSendPermissionsError, Er as ReplayDeliveryErrors, Et as DeleteEmailErrors, F as listDomains, Fi as UpdateFilterData, Fn as GetStorageStatsData, Fr as ReplyToEmailData, Ft as DeleteFilterError, G as testEndpoint, Gi as VerifyDomainResponse, Gn as Limit, Gr as RotateWebhookSecretResponses, Gt as DiscardEmailContentResponse, H as replyToEmail, Hi as VerifyDomainData, Hn as GetWebhookSecretErrors, Hr as RotateWebhookSecretError, Ht as DiscardEmailContentData, I as listEmails, Ii as UpdateFilterError, In as GetStorageStatsError, Ir as ReplyToEmailError, It as DeleteFilterErrors, J as updateEndpoint, Ji as Client, Jn as ListDeliveriesErrors, Jr as SendEmailErrors, Jt as DomainVerifyResult, K as updateAccount, Ki as VerifyDomainResponses, Kn as ListDeliveriesData, Kr as SendEmailData, Kt as DiscardEmailContentResponses, L as listEndpoints, Li as UpdateFilterErrors, Ln as GetStorageStatsErrors, Lr as ReplyToEmailErrors, Lt as DeleteFilterResponse, M as getStorageStats, Mi as UpdateEndpointInput, Mn as GetSentEmailErrors, Mr as ReplayEmailWebhooksResponse, Mt as DeleteEndpointResponse, N as getWebhookSecret, Ni as UpdateEndpointResponse, Nn as GetSentEmailResponse, Nr as ReplayEmailWebhooksResponses, Nt as DeleteEndpointResponses, O as getAccount, Oi as UpdateDomainResponses, On as GetSendPermissionsResponse, Or as ReplayDeliveryResponses, Ot as DeleteEmailResponses, P as listDeliveries, Pi as UpdateEndpointResponses, Pn as GetSentEmailResponses, Pr as ReplayResult, Pt as DeleteFilterData, Q as AccountUpdated, Qi as Options$1, Qn as ListDomainsError, Qr as SendMailResult, Qt as DownloadAttachmentsResponse, R as listFilters, Ri as UpdateFilterInput, Rn as GetStorageStatsResponse, Rr as ReplyToEmailResponse, Rt as DeleteFilterResponses, S as deleteEmail, Si as UpdateAccountResponses, Sn as GetEmailErrors, Sr as ListSentEmailsResponses, St as DeleteDomainResponse, T as discardEmailContent, Ti as UpdateDomainErrors, Tn as GetSendPermissionsData, Tr as ReplayDeliveryError, Tt as DeleteEmailError, U as rotateWebhookSecret, Ui as VerifyDomainError, Un as GetWebhookSecretResponse, Ur as RotateWebhookSecretErrors, Ut as DiscardEmailContentError, V as replayEmailWebhooks, Vi as VerifiedDomain, Vn as GetWebhookSecretError, Vr as RotateWebhookSecretData, Vt as DiscardContentResult, W as sendEmail, Wi as VerifyDomainErrors, Wn as GetWebhookSecretResponses, Wr as RotateWebhookSecretResponse, Wt as DiscardEmailContentErrors, X as verifyDomain, Xi as Config, Xn as ListDeliveriesResponses, Xr as SendEmailResponses, Xt as DownloadAttachmentsError, Y as updateFilter, Yi as ClientOptions$1, Yn as ListDeliveriesResponse, Yr as SendEmailResponse, Yt as DownloadAttachmentsData, Z as Account, Zi as CreateClientConfig, Zn as ListDomainsData, Zr as SendMailInput, Zt as DownloadAttachmentsErrors, _ as Options, _i as UpdateAccountData, _n as GetAccountErrors, _r as ListFiltersResponses, _t as CreateFilterResponses, a as PrimitiveApiError, ai as SentEmailDetail, an as EmailDetail, ar as ListEmailsResponse, at as ClientOptions, b as createFilter, bi as UpdateAccountInput, bn as GetEmailData, br as ListSentEmailsErrors, bt as DeleteDomainError, c as PrimitiveClientOptions, ci as StorageStats, cn as EmailSummary, cr as ListEndpointsError, ct as CreateEndpointErrors, d as SendResult, di as TestEndpointError, dn as ErrorResponse, dr as ListEndpointsResponses, dt as CreateEndpointResponses, ea as RequestResult, ei as SendPermissionAnyRecipient, en as DownloadRawEmailData, er as ListDomainsResponse, et as AddDomainError, f as SendThreadInput, fi as TestEndpointErrors, fn as Filter, fr as ListEnvelope, ft as CreateFilterData, g as operations, gi as UnverifiedDomain, gn as GetAccountError, gr as ListFiltersResponse, gt as CreateFilterResponse, h as createPrimitiveClient, hi as TestResult, hn as GetAccountData, hr as ListFiltersErrors, ht as CreateFilterInput, i as PrimitiveApiClientOptions, ii as SendPermissionsMeta, in as DownloadRawEmailResponses, ir as ListEmailsErrors, it as AddDomainResponses, j as getSentEmail, ji as UpdateEndpointErrors, jn as GetSentEmailError, jr as ReplayEmailWebhooksErrors, jt as DeleteEndpointErrors, k as getEmail, ki as UpdateEndpointData, kn as GetSendPermissionsResponses, kr as ReplayEmailWebhooksData, kt as DeleteEndpointData, l as ReplyInput, li as SuccessEnvelope, ln as EmailWebhookStatus, lr as ListEndpointsErrors, lt as CreateEndpointInput, m as createPrimitiveApiClient, mi as TestEndpointResponses, mn as GateFix, mr as ListFiltersError, mt as CreateFilterErrors, n as ForwardInput, na as Auth, ni as SendPermissionRule, nn as DownloadRawEmailErrors, nr as ListEmailsData, nt as AddDomainInput, o as PrimitiveApiErrorDetails, oi as SentEmailStatus, on as EmailDetailReply, or as ListEmailsResponses, ot as CreateEndpointData, p as client, pi as TestEndpointResponse, pn as GateDenial, pr as ListFiltersData, pt as CreateFilterError, q as updateDomain, qi as WebhookSecret, qn as ListDeliveriesError, qr as SendEmailError, qt as Domain, r as PrimitiveApiClient, ri as SendPermissionYourDomain, rn as DownloadRawEmailResponse, rr as ListEmailsError, rt as AddDomainResponse, s as PrimitiveClient, si as SentEmailSummary, sn as EmailStatus, sr as ListEndpointsData, st as CreateEndpointError, t as DEFAULT_BASE_URL, ta as ResponseStyle, ti as SendPermissionManagedZone, tn as DownloadRawEmailError, tr as ListDomainsResponses, tt as AddDomainErrors, u as SendInput, ui as TestEndpointData, un as Endpoint, ur as ListEndpointsResponse, ut as CreateEndpointResponse, v as addDomain, vi as UpdateAccountError, vn as GetAccountResponse, vr as ListSentEmailsData, vt as Cursor, w as deleteFilter, wi as UpdateDomainError, wn as GetEmailResponses, wr as ReplayDeliveryData, wt as DeleteEmailData, x as deleteDomain, xi as UpdateAccountResponse, xn as GetEmailError, xr as ListSentEmailsResponse, xt as DeleteDomainErrors, y as createEndpoint, yi as UpdateAccountErrors, yn as GetAccountResponses, yr as ListSentEmailsError, yt as DeleteDomainData, z as listSentEmails, zi as UpdateFilterResponse, zn as GetStorageStatsResponses, zr as ReplyToEmailResponses, zt as DeliveryStatus } from "../index-CHWqMBs6.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, DiscardContentResult, DiscardEmailContentData, DiscardEmailContentError, DiscardEmailContentErrors, DiscardEmailContentResponse, DiscardEmailContentResponses, Domain, DomainVerifyResult, DownloadAttachmentsData, DownloadAttachmentsError, DownloadAttachmentsErrors, DownloadAttachmentsResponse, DownloadAttachmentsResponses, DownloadRawEmailData, DownloadRawEmailError, DownloadRawEmailErrors, DownloadRawEmailResponse, DownloadRawEmailResponses, EmailDetail, EmailDetailReply, EmailStatus, EmailSummary, EmailWebhookStatus, Endpoint, ErrorResponse, Filter, ForwardInput, GateDenial, GateFix, GetAccountData, GetAccountError, GetAccountErrors, GetAccountResponse, GetAccountResponses, GetEmailData, GetEmailError, GetEmailErrors, GetEmailResponse, GetEmailResponses, GetSendPermissionsData, GetSendPermissionsError, GetSendPermissionsErrors, GetSendPermissionsResponse, GetSendPermissionsResponses, GetSentEmailData, GetSentEmailError, GetSentEmailErrors, GetSentEmailResponse, GetSentEmailResponses, 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, ListSentEmailsData, ListSentEmailsError, ListSentEmailsErrors, ListSentEmailsResponse, ListSentEmailsResponses, 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, SendPermissionAddress, SendPermissionAnyRecipient, SendPermissionManagedZone, SendPermissionRule, SendPermissionYourDomain, SendPermissionsMeta, SendResult, SendThreadInput, SentEmailDetail, SentEmailStatus, SentEmailSummary, 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, discardEmailContent, downloadAttachments, downloadRawEmail, getAccount, getEmail, getSendPermissions, getSentEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, listSentEmails, operations, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
|
|
@@ -620,6 +620,7 @@ var sdk_gen_exports = /* @__PURE__ */ __exportAll({
|
|
|
620
620
|
deleteEmail: () => deleteEmail,
|
|
621
621
|
deleteEndpoint: () => deleteEndpoint,
|
|
622
622
|
deleteFilter: () => deleteFilter,
|
|
623
|
+
discardEmailContent: () => discardEmailContent,
|
|
623
624
|
downloadAttachments: () => downloadAttachments,
|
|
624
625
|
downloadRawEmail: () => downloadRawEmail,
|
|
625
626
|
getAccount: () => getAccount,
|
|
@@ -686,8 +687,25 @@ const getStorageStats = (options) => (options?.client ?? client$1).get({
|
|
|
686
687
|
/**
|
|
687
688
|
* Get webhook signing secret
|
|
688
689
|
*
|
|
689
|
-
* Returns the webhook signing secret for your account. If no
|
|
690
|
-
* exists yet, one is generated automatically on first
|
|
690
|
+
* Returns the webhook signing secret for your account. If no
|
|
691
|
+
* secret exists yet, one is generated automatically on first
|
|
692
|
+
* access.
|
|
693
|
+
*
|
|
694
|
+
* Signing is account-scoped, not per-endpoint. Every webhook
|
|
695
|
+
* delivery from any of your registered endpoints is signed
|
|
696
|
+
* with this single secret. Rotate via
|
|
697
|
+
* `POST /account/webhook-secret/rotate`.
|
|
698
|
+
*
|
|
699
|
+
* **Secret format**: the returned string looks base64-shaped
|
|
700
|
+
* (e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`) but is NOT base64.
|
|
701
|
+
* Use it AS-IS as a UTF-8 string when computing HMAC over a
|
|
702
|
+
* delivery body. Base64-decoding before HMAC will silently
|
|
703
|
+
* produce mismatched signatures.
|
|
704
|
+
*
|
|
705
|
+
* See the API-level "Webhook signing" section for the full
|
|
706
|
+
* wire format (header name, signed string shape, hash algo,
|
|
707
|
+
* tolerance) including a language-agnostic verification
|
|
708
|
+
* recipe.
|
|
691
709
|
*
|
|
692
710
|
*/
|
|
693
711
|
const getWebhookSecret = (options) => (options?.client ?? client$1).get({
|
|
@@ -801,12 +819,20 @@ const verifyDomain = (options) => (options.client ?? client$1).post({
|
|
|
801
819
|
* List inbound emails
|
|
802
820
|
*
|
|
803
821
|
* Returns a paginated list of INBOUND emails received at your
|
|
804
|
-
* verified domains. Outbound messages sent via /send-mail are
|
|
805
|
-
* included; this endpoint is the inbox view, not a
|
|
806
|
-
* send/receive history.
|
|
822
|
+
* verified domains. Outbound messages sent via /send-mail are
|
|
823
|
+
* not included; this endpoint is the inbox view, not a
|
|
824
|
+
* unified send/receive history.
|
|
807
825
|
*
|
|
808
|
-
* Supports filtering by domain, status, date range, and
|
|
809
|
-
* search across subject, sender, and recipient
|
|
826
|
+
* Supports filtering by domain, status, date range, and
|
|
827
|
+
* free-text search across subject, sender, and recipient
|
|
828
|
+
* fields.
|
|
829
|
+
*
|
|
830
|
+
* For a compact text-table summary of the most recent N
|
|
831
|
+
* inbounds (no filters, no cursor pagination), the CLI ships
|
|
832
|
+
* `primitive emails:latest` as a one-line-per-email shortcut.
|
|
833
|
+
* It's TTY-aware so id columns are full UUIDs when piped, and
|
|
834
|
+
* a `--json` flag returns the same envelope this endpoint
|
|
835
|
+
* does. Use whichever fits the call site.
|
|
810
836
|
*
|
|
811
837
|
*/
|
|
812
838
|
const listEmails = (options) => (options?.client ?? client$1).get({
|
|
@@ -950,6 +976,32 @@ const replayEmailWebhooks = (options) => (options.client ?? client$1).post({
|
|
|
950
976
|
...options
|
|
951
977
|
});
|
|
952
978
|
/**
|
|
979
|
+
* Discard email content
|
|
980
|
+
*
|
|
981
|
+
* Permanently deletes the email's raw bytes, parsed body (text + HTML),
|
|
982
|
+
* and attachments while preserving metadata (sender, recipient,
|
|
983
|
+
* subject, timestamps, hashes, attachment manifest) for audit logs.
|
|
984
|
+
* Idempotent: a second call returns success with
|
|
985
|
+
* `already_discarded: true` and does no work.
|
|
986
|
+
*
|
|
987
|
+
* **Gated** on the customer's discard-content opt-in (managed in the
|
|
988
|
+
* dashboard at Settings > Webhooks). When the toggle is off, this
|
|
989
|
+
* endpoint returns `403` with code `discard_not_enabled` and a
|
|
990
|
+
* message pointing the human at the dashboard. There is intentionally
|
|
991
|
+
* no API to flip this toggle — opting in to a destructive,
|
|
992
|
+
* non-reversible operation must be a deliberate human click in the
|
|
993
|
+
* UI.
|
|
994
|
+
*
|
|
995
|
+
*/
|
|
996
|
+
const discardEmailContent = (options) => (options.client ?? client$1).post({
|
|
997
|
+
security: [{
|
|
998
|
+
scheme: "bearer",
|
|
999
|
+
type: "http"
|
|
1000
|
+
}],
|
|
1001
|
+
url: "/emails/{id}/discard-content",
|
|
1002
|
+
...options
|
|
1003
|
+
});
|
|
1004
|
+
/**
|
|
953
1005
|
* List webhook endpoints
|
|
954
1006
|
*
|
|
955
1007
|
* Returns all active (non-deleted) webhook endpoints.
|
|
@@ -965,9 +1017,22 @@ const listEndpoints = (options) => (options?.client ?? client$1).get({
|
|
|
965
1017
|
/**
|
|
966
1018
|
* Create a webhook endpoint
|
|
967
1019
|
*
|
|
968
|
-
* Creates a new webhook endpoint. If a deactivated endpoint
|
|
969
|
-
* same URL and domain exists, it is reactivated
|
|
970
|
-
* Subject to plan limits on the number of active
|
|
1020
|
+
* Creates a new webhook endpoint. If a deactivated endpoint
|
|
1021
|
+
* with the same URL and domain exists, it is reactivated
|
|
1022
|
+
* instead. Subject to plan limits on the number of active
|
|
1023
|
+
* endpoints.
|
|
1024
|
+
*
|
|
1025
|
+
* **Signing is account-scoped, not per-endpoint.** This call
|
|
1026
|
+
* does not return any signing material; every endpoint on the
|
|
1027
|
+
* account uses the same webhook secret, fetched via
|
|
1028
|
+
* `GET /account/webhook-secret`. See the API-level "Webhook
|
|
1029
|
+
* signing" section for the full wire format (header name,
|
|
1030
|
+
* signed string, hash algo, secret format, tolerance) and a
|
|
1031
|
+
* language-agnostic verification recipe.
|
|
1032
|
+
*
|
|
1033
|
+
* After creating the endpoint, fire a test delivery against
|
|
1034
|
+
* it via `POST /endpoints/{id}/test` to confirm your verifier
|
|
1035
|
+
* accepts the signature.
|
|
971
1036
|
*
|
|
972
1037
|
*/
|
|
973
1038
|
const createEndpoint = (options) => (options.client ?? client$1).post({
|
|
@@ -1486,4 +1551,4 @@ function client(options = {}) {
|
|
|
1486
1551
|
}
|
|
1487
1552
|
const operations = sdk_gen_exports;
|
|
1488
1553
|
//#endregion
|
|
1489
|
-
export {
|
|
1554
|
+
export { listSentEmails as A, updateFilter as B, getStorageStats as C, listEmails as D, listDomains as E, sendEmail as F, testEndpoint as I, updateAccount as L, replayEmailWebhooks as M, replyToEmail as N, listEndpoints as O, rotateWebhookSecret as P, updateDomain as R, getSentEmail as S, listDeliveries as T, verifyDomain as V, downloadAttachments as _, client as a, getEmail as b, operations as c, createFilter as d, deleteDomain as f, discardEmailContent as g, deleteFilter as h, PrimitiveClient as i, replayDelivery as j, listFilters 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, downloadRawEmail as v, getWebhookSecret as w, getSendPermissions as x, getAccount as y, updateEndpoint as z };
|
|
@@ -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' | 'inbound_not_repliable';
|
|
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' | 'discard_not_enabled' | 'inbound_not_repliable';
|
|
351
351
|
message: string;
|
|
352
352
|
/**
|
|
353
353
|
* Optional structured data that callers can inspect to recover
|
|
@@ -824,6 +824,25 @@ type EmailWebhookStatus = 'pending' | 'in_flight' | 'fired' | 'failed' | 'exhaus
|
|
|
824
824
|
*
|
|
825
825
|
*/
|
|
826
826
|
type SentEmailStatus = 'queued' | 'submitted_to_agent' | 'agent_failed' | 'gate_denied' | 'unknown' | 'delivered' | 'bounced' | 'deferred' | 'wait_timeout';
|
|
827
|
+
/**
|
|
828
|
+
* Narrower enum covering only the four terminal delivery
|
|
829
|
+
* outcomes returned to a synchronous `wait: true` send.
|
|
830
|
+
*
|
|
831
|
+
* On the SendMailResult shape, `delivery_status` is always
|
|
832
|
+
* equal to `status` whenever both are present (i.e. on
|
|
833
|
+
* terminal-state replays and live wait=true responses).
|
|
834
|
+
* The two fields exist so callers that want to type-narrow
|
|
835
|
+
* on "this is a delivery outcome" can pattern-match against
|
|
836
|
+
* the four-value enum without handling the broader
|
|
837
|
+
* SentEmailStatus value set (which also covers `queued`,
|
|
838
|
+
* `submitted_to_agent`, `agent_failed`, `gate_denied`,
|
|
839
|
+
* `unknown`).
|
|
840
|
+
*
|
|
841
|
+
* On async-mode and pre-terminal responses, `delivery_status`
|
|
842
|
+
* is absent and only `status` is populated. Use `status` if
|
|
843
|
+
* you want a single field that's always present.
|
|
844
|
+
*
|
|
845
|
+
*/
|
|
827
846
|
type DeliveryStatus = 'delivered' | 'bounced' | 'deferred' | 'wait_timeout';
|
|
828
847
|
/**
|
|
829
848
|
* List-row projection of a sent-email record. Drops
|
|
@@ -1077,7 +1096,20 @@ type SendMailResult = {
|
|
|
1077
1096
|
*/
|
|
1078
1097
|
from: string;
|
|
1079
1098
|
/**
|
|
1080
|
-
* Message identifier assigned by Primitive's
|
|
1099
|
+
* Message identifier assigned by Primitive's OUTBOUND relay
|
|
1100
|
+
* (the box that signs your mail and submits it to the
|
|
1101
|
+
* receiving MTA). NOT the receiver's queue id.
|
|
1102
|
+
*
|
|
1103
|
+
* The receiver may also report its own queue id in
|
|
1104
|
+
* `smtp_response_text` (e.g. `"250 2.0.0 Ok: queued as
|
|
1105
|
+
* 99D111927CDA"` from a Postfix receiver). Those two ids
|
|
1106
|
+
* refer to different mail systems and are NOT comparable.
|
|
1107
|
+
* Treat `queue_id` as Primitive-internal and the
|
|
1108
|
+
* receiver's id as remote-system-internal.
|
|
1109
|
+
*
|
|
1110
|
+
* Null on rows that never reached the relay (queued,
|
|
1111
|
+
* gate_denied, agent_failed before signing).
|
|
1112
|
+
*
|
|
1081
1113
|
*/
|
|
1082
1114
|
queue_id: string | null;
|
|
1083
1115
|
/**
|
|
@@ -1391,6 +1423,22 @@ type ReplayResult = {
|
|
|
1391
1423
|
*/
|
|
1392
1424
|
failed: number;
|
|
1393
1425
|
};
|
|
1426
|
+
type DiscardContentResult = {
|
|
1427
|
+
/**
|
|
1428
|
+
* Always `true` on a 2xx response. The content is either now
|
|
1429
|
+
* discarded as a result of this call, or was already discarded
|
|
1430
|
+
* before this call ran.
|
|
1431
|
+
*
|
|
1432
|
+
*/
|
|
1433
|
+
discarded: boolean;
|
|
1434
|
+
/**
|
|
1435
|
+
* `true` if the email's content was already discarded before
|
|
1436
|
+
* this call ran (no work was done). `false` if this call was
|
|
1437
|
+
* the one that performed the discard.
|
|
1438
|
+
*
|
|
1439
|
+
*/
|
|
1440
|
+
already_discarded: boolean;
|
|
1441
|
+
};
|
|
1394
1442
|
/**
|
|
1395
1443
|
* Resource UUID
|
|
1396
1444
|
*/
|
|
@@ -2025,6 +2073,53 @@ type ReplayEmailWebhooksResponses = {
|
|
|
2025
2073
|
};
|
|
2026
2074
|
};
|
|
2027
2075
|
type ReplayEmailWebhooksResponse = ReplayEmailWebhooksResponses[keyof ReplayEmailWebhooksResponses];
|
|
2076
|
+
type DiscardEmailContentData = {
|
|
2077
|
+
body?: never;
|
|
2078
|
+
path: {
|
|
2079
|
+
/**
|
|
2080
|
+
* Resource UUID
|
|
2081
|
+
*/
|
|
2082
|
+
id: string;
|
|
2083
|
+
};
|
|
2084
|
+
query?: never;
|
|
2085
|
+
url: '/emails/{id}/discard-content';
|
|
2086
|
+
};
|
|
2087
|
+
type DiscardEmailContentErrors = {
|
|
2088
|
+
/**
|
|
2089
|
+
* Invalid request parameters
|
|
2090
|
+
*/
|
|
2091
|
+
400: ErrorResponse;
|
|
2092
|
+
/**
|
|
2093
|
+
* Invalid or missing API key
|
|
2094
|
+
*/
|
|
2095
|
+
401: ErrorResponse;
|
|
2096
|
+
/**
|
|
2097
|
+
* Authenticated caller lacks permission for the operation
|
|
2098
|
+
*/
|
|
2099
|
+
403: ErrorResponse;
|
|
2100
|
+
/**
|
|
2101
|
+
* Resource not found
|
|
2102
|
+
*/
|
|
2103
|
+
404: ErrorResponse;
|
|
2104
|
+
/**
|
|
2105
|
+
* Rate limit exceeded
|
|
2106
|
+
*/
|
|
2107
|
+
429: ErrorResponse;
|
|
2108
|
+
/**
|
|
2109
|
+
* Primitive encountered an internal error
|
|
2110
|
+
*/
|
|
2111
|
+
500: ErrorResponse;
|
|
2112
|
+
};
|
|
2113
|
+
type DiscardEmailContentError = DiscardEmailContentErrors[keyof DiscardEmailContentErrors];
|
|
2114
|
+
type DiscardEmailContentResponses = {
|
|
2115
|
+
/**
|
|
2116
|
+
* Discard result
|
|
2117
|
+
*/
|
|
2118
|
+
200: SuccessEnvelope & {
|
|
2119
|
+
data: DiscardContentResult;
|
|
2120
|
+
};
|
|
2121
|
+
};
|
|
2122
|
+
type DiscardEmailContentResponse = DiscardEmailContentResponses[keyof DiscardEmailContentResponses];
|
|
2028
2123
|
type ListEndpointsData = {
|
|
2029
2124
|
body?: never;
|
|
2030
2125
|
path?: never;
|
|
@@ -2586,7 +2681,7 @@ type GetSentEmailResponses = {
|
|
|
2586
2681
|
};
|
|
2587
2682
|
type GetSentEmailResponse = GetSentEmailResponses[keyof GetSentEmailResponses];
|
|
2588
2683
|
declare namespace sdk_gen_d_exports {
|
|
2589
|
-
export { Options, addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, downloadAttachments, downloadRawEmail, getAccount, getEmail, getSendPermissions, getSentEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, listSentEmails, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
|
|
2684
|
+
export { Options, addDomain, createEndpoint, createFilter, deleteDomain, deleteEmail, deleteEndpoint, deleteFilter, discardEmailContent, downloadAttachments, downloadRawEmail, getAccount, getEmail, getSendPermissions, getSentEmail, getStorageStats, getWebhookSecret, listDeliveries, listDomains, listEmails, listEndpoints, listFilters, listSentEmails, replayDelivery, replayEmailWebhooks, replyToEmail, rotateWebhookSecret, sendEmail, testEndpoint, updateAccount, updateDomain, updateEndpoint, updateFilter, verifyDomain };
|
|
2590
2685
|
}
|
|
2591
2686
|
type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options$1<TData, ThrowOnError, TResponse> & {
|
|
2592
2687
|
/**
|
|
@@ -2616,8 +2711,25 @@ declare const getStorageStats: <ThrowOnError extends boolean = false>(options?:
|
|
|
2616
2711
|
/**
|
|
2617
2712
|
* Get webhook signing secret
|
|
2618
2713
|
*
|
|
2619
|
-
* Returns the webhook signing secret for your account. If no
|
|
2620
|
-
* exists yet, one is generated automatically on first
|
|
2714
|
+
* Returns the webhook signing secret for your account. If no
|
|
2715
|
+
* secret exists yet, one is generated automatically on first
|
|
2716
|
+
* access.
|
|
2717
|
+
*
|
|
2718
|
+
* Signing is account-scoped, not per-endpoint. Every webhook
|
|
2719
|
+
* delivery from any of your registered endpoints is signed
|
|
2720
|
+
* with this single secret. Rotate via
|
|
2721
|
+
* `POST /account/webhook-secret/rotate`.
|
|
2722
|
+
*
|
|
2723
|
+
* **Secret format**: the returned string looks base64-shaped
|
|
2724
|
+
* (e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`) but is NOT base64.
|
|
2725
|
+
* Use it AS-IS as a UTF-8 string when computing HMAC over a
|
|
2726
|
+
* delivery body. Base64-decoding before HMAC will silently
|
|
2727
|
+
* produce mismatched signatures.
|
|
2728
|
+
*
|
|
2729
|
+
* See the API-level "Webhook signing" section for the full
|
|
2730
|
+
* wire format (header name, signed string shape, hash algo,
|
|
2731
|
+
* tolerance) including a language-agnostic verification
|
|
2732
|
+
* recipe.
|
|
2621
2733
|
*
|
|
2622
2734
|
*/
|
|
2623
2735
|
declare const getWebhookSecret: <ThrowOnError extends boolean = false>(options?: Options<GetWebhookSecretData, ThrowOnError>) => RequestResult<GetWebhookSecretResponses, GetWebhookSecretErrors, ThrowOnError, "fields">;
|
|
@@ -2674,12 +2786,20 @@ declare const verifyDomain: <ThrowOnError extends boolean = false>(options: Opti
|
|
|
2674
2786
|
* List inbound emails
|
|
2675
2787
|
*
|
|
2676
2788
|
* Returns a paginated list of INBOUND emails received at your
|
|
2677
|
-
* verified domains. Outbound messages sent via /send-mail are
|
|
2678
|
-
* included; this endpoint is the inbox view, not a
|
|
2679
|
-
* send/receive history.
|
|
2789
|
+
* verified domains. Outbound messages sent via /send-mail are
|
|
2790
|
+
* not included; this endpoint is the inbox view, not a
|
|
2791
|
+
* unified send/receive history.
|
|
2792
|
+
*
|
|
2793
|
+
* Supports filtering by domain, status, date range, and
|
|
2794
|
+
* free-text search across subject, sender, and recipient
|
|
2795
|
+
* fields.
|
|
2680
2796
|
*
|
|
2681
|
-
*
|
|
2682
|
-
*
|
|
2797
|
+
* For a compact text-table summary of the most recent N
|
|
2798
|
+
* inbounds (no filters, no cursor pagination), the CLI ships
|
|
2799
|
+
* `primitive emails:latest` as a one-line-per-email shortcut.
|
|
2800
|
+
* It's TTY-aware so id columns are full UUIDs when piped, and
|
|
2801
|
+
* a `--json` flag returns the same envelope this endpoint
|
|
2802
|
+
* does. Use whichever fits the call site.
|
|
2683
2803
|
*
|
|
2684
2804
|
*/
|
|
2685
2805
|
declare const listEmails: <ThrowOnError extends boolean = false>(options?: Options<ListEmailsData, ThrowOnError>) => RequestResult<ListEmailsResponses, ListEmailsErrors, ThrowOnError, "fields">;
|
|
@@ -2761,6 +2881,25 @@ declare const replyToEmail: <ThrowOnError extends boolean = false>(options: Opti
|
|
|
2761
2881
|
*
|
|
2762
2882
|
*/
|
|
2763
2883
|
declare const replayEmailWebhooks: <ThrowOnError extends boolean = false>(options: Options<ReplayEmailWebhooksData, ThrowOnError>) => RequestResult<ReplayEmailWebhooksResponses, ReplayEmailWebhooksErrors, ThrowOnError, "fields">;
|
|
2884
|
+
/**
|
|
2885
|
+
* Discard email content
|
|
2886
|
+
*
|
|
2887
|
+
* Permanently deletes the email's raw bytes, parsed body (text + HTML),
|
|
2888
|
+
* and attachments while preserving metadata (sender, recipient,
|
|
2889
|
+
* subject, timestamps, hashes, attachment manifest) for audit logs.
|
|
2890
|
+
* Idempotent: a second call returns success with
|
|
2891
|
+
* `already_discarded: true` and does no work.
|
|
2892
|
+
*
|
|
2893
|
+
* **Gated** on the customer's discard-content opt-in (managed in the
|
|
2894
|
+
* dashboard at Settings > Webhooks). When the toggle is off, this
|
|
2895
|
+
* endpoint returns `403` with code `discard_not_enabled` and a
|
|
2896
|
+
* message pointing the human at the dashboard. There is intentionally
|
|
2897
|
+
* no API to flip this toggle — opting in to a destructive,
|
|
2898
|
+
* non-reversible operation must be a deliberate human click in the
|
|
2899
|
+
* UI.
|
|
2900
|
+
*
|
|
2901
|
+
*/
|
|
2902
|
+
declare const discardEmailContent: <ThrowOnError extends boolean = false>(options: Options<DiscardEmailContentData, ThrowOnError>) => RequestResult<DiscardEmailContentResponses, DiscardEmailContentErrors, ThrowOnError, "fields">;
|
|
2764
2903
|
/**
|
|
2765
2904
|
* List webhook endpoints
|
|
2766
2905
|
*
|
|
@@ -2770,9 +2909,22 @@ declare const listEndpoints: <ThrowOnError extends boolean = false>(options?: Op
|
|
|
2770
2909
|
/**
|
|
2771
2910
|
* Create a webhook endpoint
|
|
2772
2911
|
*
|
|
2773
|
-
* Creates a new webhook endpoint. If a deactivated endpoint
|
|
2774
|
-
* same URL and domain exists, it is reactivated
|
|
2775
|
-
* Subject to plan limits on the number of active
|
|
2912
|
+
* Creates a new webhook endpoint. If a deactivated endpoint
|
|
2913
|
+
* with the same URL and domain exists, it is reactivated
|
|
2914
|
+
* instead. Subject to plan limits on the number of active
|
|
2915
|
+
* endpoints.
|
|
2916
|
+
*
|
|
2917
|
+
* **Signing is account-scoped, not per-endpoint.** This call
|
|
2918
|
+
* does not return any signing material; every endpoint on the
|
|
2919
|
+
* account uses the same webhook secret, fetched via
|
|
2920
|
+
* `GET /account/webhook-secret`. See the API-level "Webhook
|
|
2921
|
+
* signing" section for the full wire format (header name,
|
|
2922
|
+
* signed string, hash algo, secret format, tolerance) and a
|
|
2923
|
+
* language-agnostic verification recipe.
|
|
2924
|
+
*
|
|
2925
|
+
* After creating the endpoint, fire a test delivery against
|
|
2926
|
+
* it via `POST /endpoints/{id}/test` to confirm your verifier
|
|
2927
|
+
* accepts the signature.
|
|
2776
2928
|
*
|
|
2777
2929
|
*/
|
|
2778
2930
|
declare const createEndpoint: <ThrowOnError extends boolean = false>(options: Options<CreateEndpointData, ThrowOnError>) => RequestResult<CreateEndpointResponses, CreateEndpointErrors, ThrowOnError, "fields">;
|
|
@@ -3054,4 +3206,4 @@ declare function createPrimitiveClient(options?: PrimitiveClientOptions): Primit
|
|
|
3054
3206
|
declare function client(options?: PrimitiveClientOptions): PrimitiveClient;
|
|
3055
3207
|
declare const operations: typeof sdk_gen_d_exports;
|
|
3056
3208
|
//#endregion
|
|
3057
|
-
export {
|
|
3209
|
+
export { AddDomainData as $, RequestOptions as $i, ListDomainsErrors as $n, SendPermissionAddress as $r, DownloadAttachmentsResponses as $t, getSendPermissions as A, UpdateEndpointError as Ai, GetSentEmailData as An, ReplayEmailWebhooksError as Ar, DeleteEndpointError as At, replayDelivery as B, UpdateFilterResponses as Bi, GetWebhookSecretData as Bn, ResourceId as Br, DeliverySummary as Bt, deleteEndpoint as C, UpdateDomainData as Ci, GetEmailResponse as Cn, PaginationMeta as Cr, DeleteDomainResponses as Ct, downloadRawEmail as D, UpdateDomainResponse as Di, GetSendPermissionsErrors as Dn, ReplayDeliveryResponse as Dr, DeleteEmailResponse as Dt, downloadAttachments as E, UpdateDomainInput as Ei, GetSendPermissionsError as En, ReplayDeliveryErrors as Er, DeleteEmailErrors as Et, listDomains as F, UpdateFilterData as Fi, GetStorageStatsData as Fn, ReplyToEmailData as Fr, DeleteFilterError as Ft, testEndpoint as G, VerifyDomainResponse as Gi, Limit as Gn, RotateWebhookSecretResponses as Gr, DiscardEmailContentResponse as Gt, replyToEmail as H, VerifyDomainData as Hi, GetWebhookSecretErrors as Hn, RotateWebhookSecretError as Hr, DiscardEmailContentData as Ht, listEmails as I, UpdateFilterError as Ii, GetStorageStatsError as In, ReplyToEmailError as Ir, DeleteFilterErrors as It, updateEndpoint as J, Client as Ji, ListDeliveriesErrors as Jn, SendEmailErrors as Jr, DomainVerifyResult as Jt, updateAccount as K, VerifyDomainResponses as Ki, ListDeliveriesData as Kn, SendEmailData as Kr, DiscardEmailContentResponses as Kt, listEndpoints as L, UpdateFilterErrors as Li, GetStorageStatsErrors as Ln, ReplyToEmailErrors as Lr, DeleteFilterResponse as Lt, getStorageStats as M, UpdateEndpointInput as Mi, GetSentEmailErrors as Mn, ReplayEmailWebhooksResponse as Mr, DeleteEndpointResponse as Mt, getWebhookSecret as N, UpdateEndpointResponse as Ni, GetSentEmailResponse as Nn, ReplayEmailWebhooksResponses as Nr, DeleteEndpointResponses as Nt, getAccount as O, UpdateDomainResponses as Oi, GetSendPermissionsResponse as On, ReplayDeliveryResponses as Or, DeleteEmailResponses as Ot, listDeliveries as P, UpdateEndpointResponses as Pi, GetSentEmailResponses as Pn, ReplayResult as Pr, DeleteFilterData as Pt, AccountUpdated as Q, Options$1 as Qi, ListDomainsError as Qn, SendMailResult as Qr, DownloadAttachmentsResponse as Qt, listFilters as R, UpdateFilterInput as Ri, GetStorageStatsResponse as Rn, ReplyToEmailResponse as Rr, DeleteFilterResponses as Rt, deleteEmail as S, UpdateAccountResponses as Si, GetEmailErrors as Sn, ListSentEmailsResponses as Sr, DeleteDomainResponse as St, discardEmailContent as T, UpdateDomainErrors as Ti, GetSendPermissionsData as Tn, ReplayDeliveryError as Tr, DeleteEmailError as Tt, rotateWebhookSecret as U, VerifyDomainError as Ui, GetWebhookSecretResponse as Un, RotateWebhookSecretErrors as Ur, DiscardEmailContentError as Ut, replayEmailWebhooks as V, VerifiedDomain as Vi, GetWebhookSecretError as Vn, RotateWebhookSecretData as Vr, DiscardContentResult as Vt, sendEmail as W, VerifyDomainErrors as Wi, GetWebhookSecretResponses as Wn, RotateWebhookSecretResponse as Wr, DiscardEmailContentErrors as Wt, verifyDomain as X, Config as Xi, ListDeliveriesResponses as Xn, SendEmailResponses as Xr, DownloadAttachmentsError as Xt, updateFilter as Y, ClientOptions$1 as Yi, ListDeliveriesResponse as Yn, SendEmailResponse as Yr, DownloadAttachmentsData as Yt, Account as Z, CreateClientConfig as Zi, ListDomainsData as Zn, SendMailInput as Zr, DownloadAttachmentsErrors as Zt, Options as _, UpdateAccountData as _i, GetAccountErrors as _n, ListFiltersResponses as _r, CreateFilterResponses as _t, PrimitiveApiError as a, SentEmailDetail as ai, EmailDetail as an, ListEmailsResponse as ar, ClientOptions as at, createFilter as b, UpdateAccountInput as bi, GetEmailData as bn, ListSentEmailsErrors as br, DeleteDomainError as bt, PrimitiveClientOptions as c, StorageStats as ci, EmailSummary as cn, ListEndpointsError as cr, CreateEndpointErrors as ct, SendResult as d, TestEndpointError as di, ErrorResponse as dn, ListEndpointsResponses as dr, CreateEndpointResponses as dt, RequestResult as ea, SendPermissionAnyRecipient as ei, DownloadRawEmailData as en, ListDomainsResponse as er, AddDomainError as et, SendThreadInput as f, TestEndpointErrors as fi, Filter as fn, ListEnvelope as fr, CreateFilterData as ft, operations as g, UnverifiedDomain as gi, GetAccountError as gn, ListFiltersResponse as gr, CreateFilterResponse as gt, createPrimitiveClient as h, TestResult as hi, GetAccountData as hn, ListFiltersErrors as hr, CreateFilterInput as ht, PrimitiveApiClientOptions as i, SendPermissionsMeta as ii, DownloadRawEmailResponses as in, ListEmailsErrors as ir, AddDomainResponses as it, getSentEmail as j, UpdateEndpointErrors as ji, GetSentEmailError as jn, ReplayEmailWebhooksErrors as jr, DeleteEndpointErrors as jt, getEmail as k, UpdateEndpointData as ki, GetSendPermissionsResponses as kn, ReplayEmailWebhooksData as kr, DeleteEndpointData as kt, ReplyInput as l, SuccessEnvelope as li, EmailWebhookStatus as ln, ListEndpointsErrors as lr, CreateEndpointInput as lt, createPrimitiveApiClient as m, TestEndpointResponses as mi, GateFix as mn, ListFiltersError as mr, CreateFilterErrors as mt, ForwardInput as n, Auth as na, SendPermissionRule as ni, DownloadRawEmailErrors as nn, ListEmailsData as nr, AddDomainInput as nt, PrimitiveApiErrorDetails as o, SentEmailStatus as oi, EmailDetailReply as on, ListEmailsResponses as or, CreateEndpointData as ot, client as p, TestEndpointResponse as pi, GateDenial as pn, ListFiltersData as pr, CreateFilterError as pt, updateDomain as q, WebhookSecret as qi, ListDeliveriesError as qn, SendEmailError as qr, Domain as qt, PrimitiveApiClient as r, SendPermissionYourDomain as ri, DownloadRawEmailResponse as rn, ListEmailsError as rr, AddDomainResponse as rt, PrimitiveClient as s, SentEmailSummary as si, EmailStatus as sn, ListEndpointsData as sr, CreateEndpointError as st, DEFAULT_BASE_URL as t, ResponseStyle as ta, SendPermissionManagedZone as ti, DownloadRawEmailError as tn, ListDomainsResponses as tr, AddDomainErrors as tt, SendInput as u, TestEndpointData as ui, Endpoint as un, ListEndpointsResponse as ur, CreateEndpointResponse as ut, addDomain as v, UpdateAccountError as vi, GetAccountResponse as vn, ListSentEmailsData as vr, Cursor as vt, deleteFilter as w, UpdateDomainError as wi, GetEmailResponses as wn, ReplayDeliveryData as wr, DeleteEmailData as wt, deleteDomain as x, UpdateAccountResponse as xi, GetEmailError as xn, ListSentEmailsResponse as xr, DeleteDomainErrors as xt, createEndpoint as y, UpdateAccountErrors as yi, GetAccountResponses as yn, ListSentEmailsError as yr, DeleteDomainData as yt, listSentEmails as z, UpdateFilterResponse as zi, GetStorageStatsResponses as zn, ReplyToEmailResponses as zr, DeliveryStatus 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-
|
|
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-CHWqMBs6.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-
|
|
2
|
+
import { a as client, i as PrimitiveClient, r as PrimitiveApiError, s as createPrimitiveClient } from "./api-DrAZhxS-.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 = {
|
|
@@ -566,9 +566,9 @@ export function createOperationCommand(operation) {
|
|
|
566
566
|
// `sdkName` for the operation. Operations without an entry fall
|
|
567
567
|
// back to no hint (silent empty array, same as before).
|
|
568
568
|
const EMPTY_RESULT_HINTS = {
|
|
569
|
-
listDeliveries: "(no results)
|
|
569
|
+
listDeliveries: "(no results) No webhook deliveries logged yet. If you have an endpoint configured but expected to see test fires here: test deliveries from `primitive endpoints:test-endpoint` are NOT logged in this list, they're synchronous and visible only in the test-endpoint command's response. Real deliveries are logged when an inbound `email.received` event fans out to your endpoints. If you have no endpoints, run `primitive endpoints:list-endpoints` to check.",
|
|
570
570
|
listEndpoints: "(no results) No webhook endpoints configured. Add one with `primitive endpoints:create-endpoint --url <your-url>`.",
|
|
571
|
-
listEmails: "(no results) No inbound emails received yet on this account.",
|
|
571
|
+
listEmails: "(no results) No inbound emails received yet on this account. Send one to a verified domain to populate this list. For a compact view, prefer `primitive emails:latest`.",
|
|
572
572
|
listDomains: "(no results) No domains on this account. Add one with `primitive domains:add-domain --domain <yourdomain.example>`.",
|
|
573
573
|
listFilters: "(no results) No filter rules configured.",
|
|
574
574
|
};
|
|
@@ -19,7 +19,15 @@ const MAX_LIMIT = 100;
|
|
|
19
19
|
// values wrap to "..." rather than blowing out terminal layout.
|
|
20
20
|
const SUBJECT_DISPLAY_WIDTH = 50;
|
|
21
21
|
const ADDRESS_DISPLAY_WIDTH = 32;
|
|
22
|
-
|
|
22
|
+
// Two ID widths: the short prefix is for human eyes (interactive
|
|
23
|
+
// TTY), the full UUID is for piped output (a script reading the row
|
|
24
|
+
// as a feed). The short prefix is useless when piped because every
|
|
25
|
+
// other operation requires the full UUID, so the AGX walkthrough
|
|
26
|
+
// kept producing a re-run with `--json` just to recover the id.
|
|
27
|
+
// Auto-switching by `process.stdout.isTTY` makes the common piped
|
|
28
|
+
// case a one-call workflow.
|
|
29
|
+
const ID_DISPLAY_WIDTH_SHORT = 8;
|
|
30
|
+
const ID_DISPLAY_WIDTH_FULL = 36;
|
|
23
31
|
const RECEIVED_DISPLAY_WIDTH = 19;
|
|
24
32
|
// Truncate to width with right-padding; values longer than width are
|
|
25
33
|
// cut to width-3 with a "..." suffix so the output is exactly `width`
|
|
@@ -48,8 +56,22 @@ export function formatReceivedAt(value) {
|
|
|
48
56
|
const pad = (n) => String(n).padStart(2, "0");
|
|
49
57
|
return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`;
|
|
50
58
|
}
|
|
51
|
-
|
|
52
|
-
|
|
59
|
+
// Decide whether to print the full UUID or the short 8-char prefix
|
|
60
|
+
// based on whether stdout is a TTY. Piped/redirected stdout (the
|
|
61
|
+
// caller is consuming the rows programmatically) gets full UUIDs;
|
|
62
|
+
// interactive terminals get the compact prefix. Pulled out as a
|
|
63
|
+
// helper so tests can drive the rendering branch without touching
|
|
64
|
+
// process.stdout.
|
|
65
|
+
export function pickIdWidth(isTty) {
|
|
66
|
+
return isTty ? ID_DISPLAY_WIDTH_SHORT : ID_DISPLAY_WIDTH_FULL;
|
|
67
|
+
}
|
|
68
|
+
export function formatRow(email, idWidth) {
|
|
69
|
+
// idWidth is one of ID_DISPLAY_WIDTH_SHORT or ID_DISPLAY_WIDTH_FULL.
|
|
70
|
+
// For SHORT, slice the UUID to the prefix length and pad. For FULL,
|
|
71
|
+
// pad to the full UUID width (UUIDs are already 36 chars, so this
|
|
72
|
+
// is effectively just an alignment guarantee for any malformed
|
|
73
|
+
// shorter id).
|
|
74
|
+
const id = truncate(email.id.slice(0, idWidth), idWidth);
|
|
53
75
|
const received = formatReceivedAt(email.received_at);
|
|
54
76
|
const from = truncate(email.sender ?? "", ADDRESS_DISPLAY_WIDTH);
|
|
55
77
|
const to = truncate(email.recipient ?? "", ADDRESS_DISPLAY_WIDTH);
|
|
@@ -60,13 +82,14 @@ export function formatRow(email) {
|
|
|
60
82
|
class EmailsLatestCommand extends Command {
|
|
61
83
|
static description = `Print the N most recent inbound emails as a one-line-per-row text table. Designed for quick triage and visual scanning. For programmatic access, use \`primitive emails:list-emails\` (full JSON envelope, cursor pagination, filters) or pass \`--json\` here for the same raw shape without pagination/filters.
|
|
62
84
|
|
|
63
|
-
|
|
85
|
+
ID display is TTY-aware. When STDOUT is a terminal, the table truncates each row's id to the first ${ID_DISPLAY_WIDTH_SHORT} characters for readability. When STDOUT is piped or redirected (the row stream is being consumed by another command), the full UUID is printed so the id can be fed straight back into \`emails:get-email\`, \`emails:delete-email\`, etc. without a separate \`--json\` round-trip.
|
|
64
86
|
|
|
65
|
-
Output streams: the column header line is written to STDERR so the row data on STDOUT stays grep/awk-friendly. \`--json\` writes everything (including the envelope) to STDOUT.`;
|
|
87
|
+
Output streams: the column header line is written to STDERR so the row data on STDOUT stays grep/awk-friendly. \`--json\` writes everything (including the envelope) to STDOUT and is equivalent to running \`emails:list-emails --limit N\` for the same N.`;
|
|
66
88
|
static summary = "Show the most recent inbound emails as a compact table";
|
|
67
89
|
static examples = [
|
|
68
90
|
"<%= config.bin %> emails:latest",
|
|
69
91
|
"<%= config.bin %> emails:latest --limit 25",
|
|
92
|
+
"<%= config.bin %> emails:latest | head -1 | awk '{print $1}' # full UUID since piped",
|
|
70
93
|
"<%= config.bin %> emails:latest --json | jq '.data[0].id'",
|
|
71
94
|
];
|
|
72
95
|
static flags = {
|
|
@@ -120,11 +143,12 @@ class EmailsLatestCommand extends Command {
|
|
|
120
143
|
process.stderr.write("No inbound emails yet. Send an email to one of your verified domains to populate this list.\n");
|
|
121
144
|
return;
|
|
122
145
|
}
|
|
146
|
+
const idWidth = pickIdWidth(Boolean(process.stdout.isTTY));
|
|
123
147
|
// Header on stderr so the table itself stays grep-friendly.
|
|
124
|
-
const header = `${"ID".padEnd(
|
|
148
|
+
const header = `${"ID".padEnd(idWidth)} ${"RECEIVED (UTC)".padEnd(RECEIVED_DISPLAY_WIDTH)} ${"FROM".padEnd(ADDRESS_DISPLAY_WIDTH)} ${"TO".padEnd(ADDRESS_DISPLAY_WIDTH)} SUBJECT`;
|
|
125
149
|
process.stderr.write(`${header}\n`);
|
|
126
150
|
for (const row of rows) {
|
|
127
|
-
this.log(formatRow(row));
|
|
151
|
+
this.log(formatRow(row, idWidth));
|
|
128
152
|
}
|
|
129
153
|
}
|
|
130
154
|
}
|
|
@@ -9,7 +9,7 @@ export const openapiDocument = {
|
|
|
9
9
|
"info": {
|
|
10
10
|
"title": "Primitive API",
|
|
11
11
|
"version": "1.0.0",
|
|
12
|
-
"description": "The Primitive API lets you manage domains, emails, webhook endpoints,\nfilters, and account settings programmatically.\n\n## Authentication\n\nAll endpoints require a Bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer prim_<your_api_key>\n```\n\nAPI keys are org-scoped. Create and manage them in your dashboard\nunder Settings > API Keys.\n\n## Rate Limiting\n\nThe API enforces a sliding window rate limit of **120 requests per\n60 seconds** per organization. When exceeded, the API returns `429`\nwith a `Retry-After` header indicating how many seconds to wait.\n\n## Pagination\n\nList endpoints use cursor-based pagination. Responses include a\n`meta` object with `total`, `limit`, and `cursor` fields. Pass the\n`cursor` value as a query parameter to fetch the next page. When\n`cursor` is `null`, there are no more results.\n\n## Response Format\n\nAll responses use a consistent envelope:\n\n```json\n{\n \"success\": true,\n \"data\": { ... },\n \"meta\": { \"total\": 42, \"limit\": 50, \"cursor\": \"...\" }\n}\n```\n\nErrors follow the same pattern:\n\n```json\n{\n \"success\": false,\n \"error\": { \"code\": \"not_found\", \"message\": \"Email not found\" }\n}\n```\n",
|
|
12
|
+
"description": "The Primitive API lets you manage domains, emails, webhook endpoints,\nfilters, and account settings programmatically.\n\n## Authentication\n\nAll endpoints require a Bearer token in the `Authorization` header:\n\n```\nAuthorization: Bearer prim_<your_api_key>\n```\n\nAPI keys are org-scoped. Create and manage them in your dashboard\nunder Settings > API Keys.\n\n## Rate Limiting\n\nThe API enforces a sliding window rate limit of **120 requests per\n60 seconds** per organization. When exceeded, the API returns `429`\nwith a `Retry-After` header indicating how many seconds to wait.\n\n## Pagination\n\nList endpoints use cursor-based pagination. Responses include a\n`meta` object with `total`, `limit`, and `cursor` fields. Pass the\n`cursor` value as a query parameter to fetch the next page. When\n`cursor` is `null`, there are no more results.\n\n## Response Format\n\nAll responses use a consistent envelope:\n\n```json\n{\n \"success\": true,\n \"data\": { ... },\n \"meta\": { \"total\": 42, \"limit\": 50, \"cursor\": \"...\" }\n}\n```\n\nErrors follow the same pattern:\n\n```json\n{\n \"success\": false,\n \"error\": { \"code\": \"not_found\", \"message\": \"Email not found\" }\n}\n```\n\n## Webhook signing\n\nOutbound webhook deliveries (configured via the `endpoints` API)\nare signed so receivers can verify they came from Primitive and\nhave not been tampered with in transit. The signing scheme is\ndeliberately simple so it can be reimplemented in any language\nin a few lines. The Node SDK's `verifyWebhookSignature` helper\nis the reference implementation; the wire details below let you\nwrite a verifier in Python, Go, Ruby, etc. without reading our\nsource.\n\n**Header**: `Primitive-Signature: t=<unix-seconds>,v1=<hex>`\n\nA legacy `MyMX-Signature` header is also sent on every delivery\nwith the same value, retained for back-compatibility with\nintegrations written before the rename. New code should read\n`Primitive-Signature`.\n\n**Signed string**: `${timestamp}.${rawBody}` where `timestamp`\nis the Unix-seconds integer from the `t=` parameter and\n`rawBody` is the exact bytes of the HTTP request body BEFORE\nany JSON decoding. Verify against the raw body, not a\nre-serialized parse, or you will silently mismatch on\ninsignificant whitespace.\n\n**Signature**: HMAC-SHA256 of the signed string, hex-encoded\n(lowercase). Use the account's webhook secret as the HMAC key,\nas a UTF-8 byte sequence.\n\n**Secret**: returned by `GET /account/webhook-secret`. The\nstring looks base64-shaped (e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`)\nbut is NOT base64; use it AS-IS as a UTF-8 string for the HMAC\nkey. Base64-decoding before HMAC will silently produce\nmismatched signatures.\n\n**Tolerance**: by convention, reject deliveries whose `t=`\ntimestamp is more than 5 minutes off your wall-clock to defend\nagainst replay attacks. The Node SDK's helper enforces this by\ndefault.\n\n**Verification recipe** (any language):\n\n```\n1. Read the raw HTTP body (do not parse).\n2. Read `Primitive-Signature: t=<ts>,v1=<sig>`.\n3. Reject if abs(now - ts) > 300 seconds.\n4. expected = HMAC_SHA256_hex(secret_utf8, f\"{ts}.{rawBody}\")\n5. Constant-time compare expected to sig. Reject if not equal.\n```\n\nFor Node, use `verifyWebhookSignature` from\n`@primitivedotdev/sdk/webhook` (or the higher-level\n`handleWebhook` helper if you want a one-liner). For other\nlanguages, the recipe above is everything you need.\n\nTest deliveries: `POST /endpoints/{id}/test` triggers a fake\ndelivery to your endpoint URL, signed with your real account\nsecret, so you can confirm verification end-to-end without\nneeding real inbound mail. The test response carries the exact\n`signature` header value sent on the wire so you can compare\nstrings directly.\n",
|
|
13
13
|
"contact": {
|
|
14
14
|
"name": "Primitive",
|
|
15
15
|
"url": "https://primitive.dev"
|
|
@@ -193,7 +193,7 @@ export const openapiDocument = {
|
|
|
193
193
|
"get": {
|
|
194
194
|
"operationId": "getWebhookSecret",
|
|
195
195
|
"summary": "Get webhook signing secret",
|
|
196
|
-
"description": "Returns the webhook signing secret for your account. If no
|
|
196
|
+
"description": "Returns the webhook signing secret for your account. If no\nsecret exists yet, one is generated automatically on first\naccess.\n\nSigning is account-scoped, not per-endpoint. Every webhook\ndelivery from any of your registered endpoints is signed\nwith this single secret. Rotate via\n`POST /account/webhook-secret/rotate`.\n\n**Secret format**: the returned string looks base64-shaped\n(e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`) but is NOT base64.\nUse it AS-IS as a UTF-8 string when computing HMAC over a\ndelivery body. Base64-decoding before HMAC will silently\nproduce mismatched signatures.\n\nSee the API-level \"Webhook signing\" section for the full\nwire format (header name, signed string shape, hash algo,\ntolerance) including a language-agnostic verification\nrecipe.\n",
|
|
197
197
|
"tags": [
|
|
198
198
|
"Account"
|
|
199
199
|
],
|
|
@@ -533,7 +533,7 @@ export const openapiDocument = {
|
|
|
533
533
|
"get": {
|
|
534
534
|
"operationId": "listEmails",
|
|
535
535
|
"summary": "List inbound emails",
|
|
536
|
-
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are
|
|
536
|
+
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are\nnot included; this endpoint is the inbox view, not a\nunified send/receive history.\n\nSupports filtering by domain, status, date range, and\nfree-text search across subject, sender, and recipient\nfields.\n\nFor a compact text-table summary of the most recent N\ninbounds (no filters, no cursor pagination), the CLI ships\n`primitive emails:latest` as a one-line-per-email shortcut.\nIt's TTY-aware so id columns are full UUIDs when piped, and\na `--json` flag returns the same envelope this endpoint\ndoes. Use whichever fits the call site.\n",
|
|
537
537
|
"tags": [
|
|
538
538
|
"Emails"
|
|
539
539
|
],
|
|
@@ -978,6 +978,66 @@ export const openapiDocument = {
|
|
|
978
978
|
}
|
|
979
979
|
}
|
|
980
980
|
},
|
|
981
|
+
"/emails/{id}/discard-content": {
|
|
982
|
+
"parameters": [
|
|
983
|
+
{
|
|
984
|
+
"$ref": "#/components/parameters/ResourceId"
|
|
985
|
+
}
|
|
986
|
+
],
|
|
987
|
+
"post": {
|
|
988
|
+
"operationId": "discardEmailContent",
|
|
989
|
+
"summary": "Discard email content",
|
|
990
|
+
"description": "Permanently deletes the email's raw bytes, parsed body (text + HTML),\nand attachments while preserving metadata (sender, recipient,\nsubject, timestamps, hashes, attachment manifest) for audit logs.\nIdempotent: a second call returns success with\n`already_discarded: true` and does no work.\n\n**Gated** on the customer's discard-content opt-in (managed in the\ndashboard at Settings > Webhooks). When the toggle is off, this\nendpoint returns `403` with code `discard_not_enabled` and a\nmessage pointing the human at the dashboard. There is intentionally\nno API to flip this toggle — opting in to a destructive,\nnon-reversible operation must be a deliberate human click in the\nUI.\n",
|
|
991
|
+
"tags": [
|
|
992
|
+
"Emails"
|
|
993
|
+
],
|
|
994
|
+
"responses": {
|
|
995
|
+
"200": {
|
|
996
|
+
"description": "Discard result",
|
|
997
|
+
"content": {
|
|
998
|
+
"application/json": {
|
|
999
|
+
"schema": {
|
|
1000
|
+
"allOf": [
|
|
1001
|
+
{
|
|
1002
|
+
"$ref": "#/components/schemas/SuccessEnvelope"
|
|
1003
|
+
},
|
|
1004
|
+
{
|
|
1005
|
+
"type": "object",
|
|
1006
|
+
"properties": {
|
|
1007
|
+
"data": {
|
|
1008
|
+
"$ref": "#/components/schemas/DiscardContentResult"
|
|
1009
|
+
}
|
|
1010
|
+
},
|
|
1011
|
+
"required": [
|
|
1012
|
+
"data"
|
|
1013
|
+
]
|
|
1014
|
+
}
|
|
1015
|
+
]
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
},
|
|
1020
|
+
"400": {
|
|
1021
|
+
"$ref": "#/components/responses/ValidationError"
|
|
1022
|
+
},
|
|
1023
|
+
"401": {
|
|
1024
|
+
"$ref": "#/components/responses/Unauthorized"
|
|
1025
|
+
},
|
|
1026
|
+
"403": {
|
|
1027
|
+
"$ref": "#/components/responses/Forbidden"
|
|
1028
|
+
},
|
|
1029
|
+
"404": {
|
|
1030
|
+
"$ref": "#/components/responses/NotFound"
|
|
1031
|
+
},
|
|
1032
|
+
"429": {
|
|
1033
|
+
"$ref": "#/components/responses/RateLimited"
|
|
1034
|
+
},
|
|
1035
|
+
"500": {
|
|
1036
|
+
"$ref": "#/components/responses/InternalError"
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
981
1041
|
"/endpoints": {
|
|
982
1042
|
"get": {
|
|
983
1043
|
"operationId": "listEndpoints",
|
|
@@ -1020,7 +1080,7 @@ export const openapiDocument = {
|
|
|
1020
1080
|
"post": {
|
|
1021
1081
|
"operationId": "createEndpoint",
|
|
1022
1082
|
"summary": "Create a webhook endpoint",
|
|
1023
|
-
"description": "Creates a new webhook endpoint. If a deactivated endpoint
|
|
1083
|
+
"description": "Creates a new webhook endpoint. If a deactivated endpoint\nwith the same URL and domain exists, it is reactivated\ninstead. Subject to plan limits on the number of active\nendpoints.\n\n**Signing is account-scoped, not per-endpoint.** This call\ndoes not return any signing material; every endpoint on the\naccount uses the same webhook secret, fetched via\n`GET /account/webhook-secret`. See the API-level \"Webhook\nsigning\" section for the full wire format (header name,\nsigned string, hash algo, secret format, tolerance) and a\nlanguage-agnostic verification recipe.\n\nAfter creating the endpoint, fire a test delivery against\nit via `POST /endpoints/{id}/test` to confirm your verifier\naccepts the signature.\n",
|
|
1024
1084
|
"tags": [
|
|
1025
1085
|
"Endpoints"
|
|
1026
1086
|
],
|
|
@@ -2096,6 +2156,7 @@ export const openapiDocument = {
|
|
|
2096
2156
|
"outbound_capacity_exhausted",
|
|
2097
2157
|
"outbound_response_malformed",
|
|
2098
2158
|
"outbound_relay_failed",
|
|
2159
|
+
"discard_not_enabled",
|
|
2099
2160
|
"inbound_not_repliable"
|
|
2100
2161
|
]
|
|
2101
2162
|
},
|
|
@@ -3012,6 +3073,7 @@ export const openapiDocument = {
|
|
|
3012
3073
|
},
|
|
3013
3074
|
"DeliveryStatus": {
|
|
3014
3075
|
"type": "string",
|
|
3076
|
+
"description": "Narrower enum covering only the four terminal delivery\noutcomes returned to a synchronous `wait: true` send.\n\nOn the SendMailResult shape, `delivery_status` is always\nequal to `status` whenever both are present (i.e. on\nterminal-state replays and live wait=true responses).\nThe two fields exist so callers that want to type-narrow\non \"this is a delivery outcome\" can pattern-match against\nthe four-value enum without handling the broader\nSentEmailStatus value set (which also covers `queued`,\n`submitted_to_agent`, `agent_failed`, `gate_denied`,\n`unknown`).\n\nOn async-mode and pre-terminal responses, `delivery_status`\nis absent and only `status` is populated. Use `status` if\nyou want a single field that's always present.\n",
|
|
3015
3077
|
"enum": [
|
|
3016
3078
|
"delivered",
|
|
3017
3079
|
"bounced",
|
|
@@ -3274,7 +3336,7 @@ export const openapiDocument = {
|
|
|
3274
3336
|
"string",
|
|
3275
3337
|
"null"
|
|
3276
3338
|
],
|
|
3277
|
-
"description": "Message identifier assigned by Primitive's
|
|
3339
|
+
"description": "Message identifier assigned by Primitive's OUTBOUND relay\n(the box that signs your mail and submits it to the\nreceiving MTA). NOT the receiver's queue id.\n\nThe receiver may also report its own queue id in\n`smtp_response_text` (e.g. `\"250 2.0.0 Ok: queued as\n99D111927CDA\"` from a Postfix receiver). Those two ids\nrefer to different mail systems and are NOT comparable.\nTreat `queue_id` as Primitive-internal and the\nreceiver's id as remote-system-internal.\n\nNull on rows that never reached the relay (queued,\ngate_denied, agent_failed before signing).\n"
|
|
3278
3340
|
},
|
|
3279
3341
|
"accepted": {
|
|
3280
3342
|
"type": "array",
|
|
@@ -3856,6 +3918,23 @@ export const openapiDocument = {
|
|
|
3856
3918
|
"delivered",
|
|
3857
3919
|
"failed"
|
|
3858
3920
|
]
|
|
3921
|
+
},
|
|
3922
|
+
"DiscardContentResult": {
|
|
3923
|
+
"type": "object",
|
|
3924
|
+
"properties": {
|
|
3925
|
+
"discarded": {
|
|
3926
|
+
"type": "boolean",
|
|
3927
|
+
"description": "Always `true` on a 2xx response. The content is either now\ndiscarded as a result of this call, or was already discarded\nbefore this call ran.\n"
|
|
3928
|
+
},
|
|
3929
|
+
"already_discarded": {
|
|
3930
|
+
"type": "boolean",
|
|
3931
|
+
"description": "`true` if the email's content was already discarded before\nthis call ran (no work was done). `false` if this call was\nthe one that performed the discard.\n"
|
|
3932
|
+
}
|
|
3933
|
+
},
|
|
3934
|
+
"required": [
|
|
3935
|
+
"discarded",
|
|
3936
|
+
"already_discarded"
|
|
3937
|
+
]
|
|
3859
3938
|
}
|
|
3860
3939
|
}
|
|
3861
3940
|
}
|
|
@@ -152,7 +152,7 @@ export const operationManifest = [
|
|
|
152
152
|
"binaryResponse": false,
|
|
153
153
|
"bodyRequired": false,
|
|
154
154
|
"command": "get-webhook-secret",
|
|
155
|
-
"description": "Returns the webhook signing secret for your account. If no
|
|
155
|
+
"description": "Returns the webhook signing secret for your account. If no\nsecret exists yet, one is generated automatically on first\naccess.\n\nSigning is account-scoped, not per-endpoint. Every webhook\ndelivery from any of your registered endpoints is signed\nwith this single secret. Rotate via\n`POST /account/webhook-secret/rotate`.\n\n**Secret format**: the returned string looks base64-shaped\n(e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`) but is NOT base64.\nUse it AS-IS as a UTF-8 string when computing HMAC over a\ndelivery body. Base64-decoding before HMAC will silently\nproduce mismatched signatures.\n\nSee the API-level \"Webhook signing\" section for the full\nwire format (header name, signed string shape, hash algo,\ntolerance) including a language-agnostic verification\nrecipe.\n",
|
|
156
156
|
"hasJsonBody": false,
|
|
157
157
|
"method": "GET",
|
|
158
158
|
"operationId": "getWebhookSecret",
|
|
@@ -664,6 +664,48 @@ export const operationManifest = [
|
|
|
664
664
|
"tag": "Emails",
|
|
665
665
|
"tagCommand": "emails"
|
|
666
666
|
},
|
|
667
|
+
{
|
|
668
|
+
"binaryResponse": false,
|
|
669
|
+
"bodyRequired": false,
|
|
670
|
+
"command": "discard-email-content",
|
|
671
|
+
"description": "Permanently deletes the email's raw bytes, parsed body (text + HTML),\nand attachments while preserving metadata (sender, recipient,\nsubject, timestamps, hashes, attachment manifest) for audit logs.\nIdempotent: a second call returns success with\n`already_discarded: true` and does no work.\n\n**Gated** on the customer's discard-content opt-in (managed in the\ndashboard at Settings > Webhooks). When the toggle is off, this\nendpoint returns `403` with code `discard_not_enabled` and a\nmessage pointing the human at the dashboard. There is intentionally\nno API to flip this toggle — opting in to a destructive,\nnon-reversible operation must be a deliberate human click in the\nUI.\n",
|
|
672
|
+
"hasJsonBody": false,
|
|
673
|
+
"method": "POST",
|
|
674
|
+
"operationId": "discardEmailContent",
|
|
675
|
+
"path": "/emails/{id}/discard-content",
|
|
676
|
+
"pathParams": [
|
|
677
|
+
{
|
|
678
|
+
"description": "Resource UUID",
|
|
679
|
+
"enum": null,
|
|
680
|
+
"name": "id",
|
|
681
|
+
"required": true,
|
|
682
|
+
"type": "string"
|
|
683
|
+
}
|
|
684
|
+
],
|
|
685
|
+
"queryParams": [],
|
|
686
|
+
"requestSchema": null,
|
|
687
|
+
"responseSchema": {
|
|
688
|
+
"type": "object",
|
|
689
|
+
"properties": {
|
|
690
|
+
"discarded": {
|
|
691
|
+
"type": "boolean",
|
|
692
|
+
"description": "Always `true` on a 2xx response. The content is either now\ndiscarded as a result of this call, or was already discarded\nbefore this call ran.\n"
|
|
693
|
+
},
|
|
694
|
+
"already_discarded": {
|
|
695
|
+
"type": "boolean",
|
|
696
|
+
"description": "`true` if the email's content was already discarded before\nthis call ran (no work was done). `false` if this call was\nthe one that performed the discard.\n"
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
"required": [
|
|
700
|
+
"discarded",
|
|
701
|
+
"already_discarded"
|
|
702
|
+
]
|
|
703
|
+
},
|
|
704
|
+
"sdkName": "discardEmailContent",
|
|
705
|
+
"summary": "Discard email content",
|
|
706
|
+
"tag": "Emails",
|
|
707
|
+
"tagCommand": "emails"
|
|
708
|
+
},
|
|
667
709
|
{
|
|
668
710
|
"binaryResponse": true,
|
|
669
711
|
"bodyRequired": false,
|
|
@@ -1029,7 +1071,7 @@ export const operationManifest = [
|
|
|
1029
1071
|
"binaryResponse": false,
|
|
1030
1072
|
"bodyRequired": false,
|
|
1031
1073
|
"command": "list-emails",
|
|
1032
|
-
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are
|
|
1074
|
+
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are\nnot included; this endpoint is the inbox view, not a\nunified send/receive history.\n\nSupports filtering by domain, status, date range, and\nfree-text search across subject, sender, and recipient\nfields.\n\nFor a compact text-table summary of the most recent N\ninbounds (no filters, no cursor pagination), the CLI ships\n`primitive emails:latest` as a one-line-per-email shortcut.\nIt's TTY-aware so id columns are full UUIDs when piped, and\na `--json` flag returns the same envelope this endpoint\ndoes. Use whichever fits the call site.\n",
|
|
1033
1075
|
"hasJsonBody": false,
|
|
1034
1076
|
"method": "GET",
|
|
1035
1077
|
"operationId": "listEmails",
|
|
@@ -1244,7 +1286,7 @@ export const operationManifest = [
|
|
|
1244
1286
|
"binaryResponse": false,
|
|
1245
1287
|
"bodyRequired": true,
|
|
1246
1288
|
"command": "create-endpoint",
|
|
1247
|
-
"description": "Creates a new webhook endpoint. If a deactivated endpoint
|
|
1289
|
+
"description": "Creates a new webhook endpoint. If a deactivated endpoint\nwith the same URL and domain exists, it is reactivated\ninstead. Subject to plan limits on the number of active\nendpoints.\n\n**Signing is account-scoped, not per-endpoint.** This call\ndoes not return any signing material; every endpoint on the\naccount uses the same webhook secret, fetched via\n`GET /account/webhook-secret`. See the API-level \"Webhook\nsigning\" section for the full wire format (header name,\nsigned string, hash algo, secret format, tolerance) and a\nlanguage-agnostic verification recipe.\n\nAfter creating the endpoint, fire a test delivery against\nit via `POST /endpoints/{id}/test` to confirm your verifier\naccepts the signature.\n",
|
|
1248
1290
|
"hasJsonBody": true,
|
|
1249
1291
|
"method": "POST",
|
|
1250
1292
|
"operationId": "createEndpoint",
|
|
@@ -2836,7 +2878,7 @@ export const operationManifest = [
|
|
|
2836
2878
|
"string",
|
|
2837
2879
|
"null"
|
|
2838
2880
|
],
|
|
2839
|
-
"description": "Message identifier assigned by Primitive's
|
|
2881
|
+
"description": "Message identifier assigned by Primitive's OUTBOUND relay\n(the box that signs your mail and submits it to the\nreceiving MTA). NOT the receiver's queue id.\n\nThe receiver may also report its own queue id in\n`smtp_response_text` (e.g. `\"250 2.0.0 Ok: queued as\n99D111927CDA\"` from a Postfix receiver). Those two ids\nrefer to different mail systems and are NOT comparable.\nTreat `queue_id` as Primitive-internal and the\nreceiver's id as remote-system-internal.\n\nNull on rows that never reached the relay (queued,\ngate_denied, agent_failed before signing).\n"
|
|
2840
2882
|
},
|
|
2841
2883
|
"accepted": {
|
|
2842
2884
|
"type": "array",
|
|
@@ -2866,6 +2908,7 @@ export const operationManifest = [
|
|
|
2866
2908
|
},
|
|
2867
2909
|
"delivery_status": {
|
|
2868
2910
|
"type": "string",
|
|
2911
|
+
"description": "Narrower enum covering only the four terminal delivery\noutcomes returned to a synchronous `wait: true` send.\n\nOn the SendMailResult shape, `delivery_status` is always\nequal to `status` whenever both are present (i.e. on\nterminal-state replays and live wait=true responses).\nThe two fields exist so callers that want to type-narrow\non \"this is a delivery outcome\" can pattern-match against\nthe four-value enum without handling the broader\nSentEmailStatus value set (which also covers `queued`,\n`submitted_to_agent`, `agent_failed`, `gate_denied`,\n`unknown`).\n\nOn async-mode and pre-terminal responses, `delivery_status`\nis absent and only `status` is populated. Use `status` if\nyou want a single field that's always present.\n",
|
|
2869
2912
|
"enum": [
|
|
2870
2913
|
"delivered",
|
|
2871
2914
|
"bounced",
|
|
@@ -3014,7 +3057,7 @@ export const operationManifest = [
|
|
|
3014
3057
|
"string",
|
|
3015
3058
|
"null"
|
|
3016
3059
|
],
|
|
3017
|
-
"description": "Message identifier assigned by Primitive's
|
|
3060
|
+
"description": "Message identifier assigned by Primitive's OUTBOUND relay\n(the box that signs your mail and submits it to the\nreceiving MTA). NOT the receiver's queue id.\n\nThe receiver may also report its own queue id in\n`smtp_response_text` (e.g. `\"250 2.0.0 Ok: queued as\n99D111927CDA\"` from a Postfix receiver). Those two ids\nrefer to different mail systems and are NOT comparable.\nTreat `queue_id` as Primitive-internal and the\nreceiver's id as remote-system-internal.\n\nNull on rows that never reached the relay (queued,\ngate_denied, agent_failed before signing).\n"
|
|
3018
3061
|
},
|
|
3019
3062
|
"accepted": {
|
|
3020
3063
|
"type": "array",
|
|
@@ -3044,6 +3087,7 @@ export const operationManifest = [
|
|
|
3044
3087
|
},
|
|
3045
3088
|
"delivery_status": {
|
|
3046
3089
|
"type": "string",
|
|
3090
|
+
"description": "Narrower enum covering only the four terminal delivery\noutcomes returned to a synchronous `wait: true` send.\n\nOn the SendMailResult shape, `delivery_status` is always\nequal to `status` whenever both are present (i.e. on\nterminal-state replays and live wait=true responses).\nThe two fields exist so callers that want to type-narrow\non \"this is a delivery outcome\" can pattern-match against\nthe four-value enum without handling the broader\nSentEmailStatus value set (which also covers `queued`,\n`submitted_to_agent`, `agent_failed`, `gate_denied`,\n`unknown`).\n\nOn async-mode and pre-terminal responses, `delivery_status`\nis absent and only `status` is populated. Use `status` if\nyou want a single field that's always present.\n",
|
|
3047
3091
|
"enum": [
|
|
3048
3092
|
"delivered",
|
|
3049
3093
|
"bounced",
|
package/oclif.manifest.json
CHANGED
|
@@ -201,10 +201,11 @@
|
|
|
201
201
|
"emails:latest": {
|
|
202
202
|
"aliases": [],
|
|
203
203
|
"args": {},
|
|
204
|
-
"description": "Print the N most recent inbound emails as a one-line-per-row text table. Designed for quick triage and visual scanning. For programmatic access, use `primitive emails:list-emails` (full JSON envelope, cursor pagination, filters) or pass `--json` here for the same raw shape without pagination/filters.\n\n
|
|
204
|
+
"description": "Print the N most recent inbound emails as a one-line-per-row text table. Designed for quick triage and visual scanning. For programmatic access, use `primitive emails:list-emails` (full JSON envelope, cursor pagination, filters) or pass `--json` here for the same raw shape without pagination/filters.\n\n ID display is TTY-aware. When STDOUT is a terminal, the table truncates each row's id to the first 8 characters for readability. When STDOUT is piped or redirected (the row stream is being consumed by another command), the full UUID is printed so the id can be fed straight back into `emails:get-email`, `emails:delete-email`, etc. without a separate `--json` round-trip.\n\n Output streams: the column header line is written to STDERR so the row data on STDOUT stays grep/awk-friendly. `--json` writes everything (including the envelope) to STDOUT and is equivalent to running `emails:list-emails --limit N` for the same N.",
|
|
205
205
|
"examples": [
|
|
206
206
|
"<%= config.bin %> emails:latest",
|
|
207
207
|
"<%= config.bin %> emails:latest --limit 25",
|
|
208
|
+
"<%= config.bin %> emails:latest | head -1 | awk '{print $1}' # full UUID since piped",
|
|
208
209
|
"<%= config.bin %> emails:latest --json | jq '.data[0].id'"
|
|
209
210
|
],
|
|
210
211
|
"flags": {
|
|
@@ -316,7 +317,7 @@
|
|
|
316
317
|
"account:get-webhook-secret": {
|
|
317
318
|
"aliases": [],
|
|
318
319
|
"args": {},
|
|
319
|
-
"description": "Returns the webhook signing secret for your account. If no
|
|
320
|
+
"description": "Returns the webhook signing secret for your account. If no\nsecret exists yet, one is generated automatically on first\naccess.\n\nSigning is account-scoped, not per-endpoint. Every webhook\ndelivery from any of your registered endpoints is signed\nwith this single secret. Rotate via\n`POST /account/webhook-secret/rotate`.\n\n**Secret format**: the returned string looks base64-shaped\n(e.g. `XNHBBW8VqoBjRfNs1tkZj11jTk...`) but is NOT base64.\nUse it AS-IS as a UTF-8 string when computing HMAC over a\ndelivery body. Base64-decoding before HMAC will silently\nproduce mismatched signatures.\n\nSee the API-level \"Webhook signing\" section for the full\nwire format (header name, signed string shape, hash algo,\ntolerance) including a language-agnostic verification\nrecipe.\n",
|
|
320
321
|
"flags": {
|
|
321
322
|
"api-key": {
|
|
322
323
|
"description": "Primitive API key (defaults to PRIMITIVE_API_KEY)",
|
|
@@ -708,6 +709,46 @@
|
|
|
708
709
|
"summary": "Delete an email",
|
|
709
710
|
"enableJsonFlag": false
|
|
710
711
|
},
|
|
712
|
+
"emails:discard-email-content": {
|
|
713
|
+
"aliases": [],
|
|
714
|
+
"args": {},
|
|
715
|
+
"description": "Permanently deletes the email's raw bytes, parsed body (text + HTML),\nand attachments while preserving metadata (sender, recipient,\nsubject, timestamps, hashes, attachment manifest) for audit logs.\nIdempotent: a second call returns success with\n`already_discarded: true` and does no work.\n\n**Gated** on the customer's discard-content opt-in (managed in the\ndashboard at Settings > Webhooks). When the toggle is off, this\nendpoint returns `403` with code `discard_not_enabled` and a\nmessage pointing the human at the dashboard. There is intentionally\nno API to flip this toggle — opting in to a destructive,\nnon-reversible operation must be a deliberate human click in the\nUI.\n",
|
|
716
|
+
"flags": {
|
|
717
|
+
"api-key": {
|
|
718
|
+
"description": "Primitive API key (defaults to PRIMITIVE_API_KEY)",
|
|
719
|
+
"env": "PRIMITIVE_API_KEY",
|
|
720
|
+
"name": "api-key",
|
|
721
|
+
"hasDynamicHelp": false,
|
|
722
|
+
"multiple": false,
|
|
723
|
+
"type": "option"
|
|
724
|
+
},
|
|
725
|
+
"base-url": {
|
|
726
|
+
"description": "API base URL (defaults to PRIMITIVE_API_URL or production)",
|
|
727
|
+
"env": "PRIMITIVE_API_URL",
|
|
728
|
+
"name": "base-url",
|
|
729
|
+
"hasDynamicHelp": false,
|
|
730
|
+
"multiple": false,
|
|
731
|
+
"type": "option"
|
|
732
|
+
},
|
|
733
|
+
"id": {
|
|
734
|
+
"description": "Resource UUID",
|
|
735
|
+
"name": "id",
|
|
736
|
+
"required": true,
|
|
737
|
+
"hasDynamicHelp": false,
|
|
738
|
+
"multiple": false,
|
|
739
|
+
"type": "option"
|
|
740
|
+
}
|
|
741
|
+
},
|
|
742
|
+
"hasDynamicHelp": false,
|
|
743
|
+
"hiddenAliases": [],
|
|
744
|
+
"id": "emails:discard-email-content",
|
|
745
|
+
"pluginAlias": "@primitivedotdev/sdk",
|
|
746
|
+
"pluginName": "@primitivedotdev/sdk",
|
|
747
|
+
"pluginType": "core",
|
|
748
|
+
"strict": true,
|
|
749
|
+
"summary": "Discard email content",
|
|
750
|
+
"enableJsonFlag": false
|
|
751
|
+
},
|
|
711
752
|
"emails:download-attachments": {
|
|
712
753
|
"aliases": [],
|
|
713
754
|
"args": {},
|
|
@@ -861,7 +902,7 @@
|
|
|
861
902
|
"emails:list-emails": {
|
|
862
903
|
"aliases": [],
|
|
863
904
|
"args": {},
|
|
864
|
-
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are
|
|
905
|
+
"description": "Returns a paginated list of INBOUND emails received at your\nverified domains. Outbound messages sent via /send-mail are\nnot included; this endpoint is the inbox view, not a\nunified send/receive history.\n\nSupports filtering by domain, status, date range, and\nfree-text search across subject, sender, and recipient\nfields.\n\nFor a compact text-table summary of the most recent N\ninbounds (no filters, no cursor pagination), the CLI ships\n`primitive emails:latest` as a one-line-per-email shortcut.\nIt's TTY-aware so id columns are full UUIDs when piped, and\na `--json` flag returns the same envelope this endpoint\ndoes. Use whichever fits the call site.\n",
|
|
865
906
|
"flags": {
|
|
866
907
|
"api-key": {
|
|
867
908
|
"description": "Primitive API key (defaults to PRIMITIVE_API_KEY)",
|
|
@@ -989,7 +1030,7 @@
|
|
|
989
1030
|
"endpoints:create-endpoint": {
|
|
990
1031
|
"aliases": [],
|
|
991
1032
|
"args": {},
|
|
992
|
-
"description": "Creates a new webhook endpoint. If a deactivated endpoint
|
|
1033
|
+
"description": "Creates a new webhook endpoint. If a deactivated endpoint\nwith the same URL and domain exists, it is reactivated\ninstead. Subject to plan limits on the number of active\nendpoints.\n\n**Signing is account-scoped, not per-endpoint.** This call\ndoes not return any signing material; every endpoint on the\naccount uses the same webhook secret, fetched via\n`GET /account/webhook-secret`. See the API-level \"Webhook\nsigning\" section for the full wire format (header name,\nsigned string, hash algo, secret format, tolerance) and a\nlanguage-agnostic verification recipe.\n\nAfter creating the endpoint, fire a test delivery against\nit via `POST /endpoints/{id}/test` to confirm your verifier\naccepts the signature.\n\n\nBody fields requiring --raw-body JSON (these are not exposed as flags):\n rules object Endpoint-specific filtering rules\n(* = required. Scalar body fields are exposed as individual --flag-name flags; see FLAGS above.)",
|
|
993
1034
|
"flags": {
|
|
994
1035
|
"api-key": {
|
|
995
1036
|
"description": "Primitive API key (defaults to PRIMITIVE_API_KEY)",
|
|
@@ -1910,5 +1951,5 @@
|
|
|
1910
1951
|
"enableJsonFlag": false
|
|
1911
1952
|
}
|
|
1912
1953
|
},
|
|
1913
|
-
"version": "0.
|
|
1954
|
+
"version": "0.17.0"
|
|
1914
1955
|
}
|