@stackshift-cloud/sdk 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,6 +34,24 @@ Set your API key:
34
34
  STACKSHIFT_API_KEY=sk_live_xxx
35
35
  ```
36
36
 
37
+ ## Partner platforms
38
+
39
+ Staff-enabled partner accounts buy domains for merchants from their StackShift wallet; StackShift registers the domain, sets up Mail and creates a warmed-up brand tagged with your merchant reference. Use an API token with the `partner:manage` scope (and `mail:manage` to run campaigns) on your server:
40
+
41
+ ```ts
42
+ const domain = await stackshift.partner.purchaseDomain({
43
+ domain: 'merchantshop.com',
44
+ years: 1,
45
+ merchantRef: 'm_123',
46
+ registrant: { first_name: 'Ada', last_name: 'Obi', email: 'ada@merchantshop.com', phone: '+2348012345678', address: '1 Marina', city: 'Lagos', state: 'Lagos', postal_code: '101001', country: 'NG' },
47
+ brand: { name: 'Merchant Shop', postalAddress: '1 Marina, Lagos, Nigeria' },
48
+ replies: { mode: 'forward', forwardTo: 'ada@gmail.com' },
49
+ }, { idempotencyKey: 'order-m_123-1' })
50
+ const status = await stackshift.partner.getDomain(domain.id)
51
+ ```
52
+
53
+ `partner` also exposes `overview`, `updateSettings`, `listDomains` (with `q` and `attention` to find the merchants that need you), `retryDomain`, `getDiagnosis`, `restoreDns`, `transferOut`, `resumeBrand`, `getComplaints`, `listComplaintSources`, `suppressNeverOpened`, `undoSuppression`, `usage`, `listRequests` and `createRequest`. `transferOut` needs the `partner:transfer` scope (or `*`); `partner:manage` alone is refused. Purchases are capped at 30 per minute and, per partner, at 25 domains in a rolling 24 hours (429 `daily_purchase_limit`; staff can raise it). Validation errors are 400, state conflicts are 409. Subscribe to the `partner.*` event types with `mail.webhooks.create` and send campaigns through the brand in `domain.brandId`.
54
+
37
55
  ## AI credits
38
56
 
39
57
  AI credits are account-scoped. Inspect the balance and usage, create a top-up checkout, or choose managed billing versus your own provider key:
@@ -2,7 +2,8 @@ export type AssetMediaKind = 'image' | 'video';
2
2
  export type AssetTransformOutputKind = 'image' | 'video' | 'audio' | 'thumbnail';
3
3
  export type AssetAnimationPolicy = 'first' | 'preserve' | 'reject';
4
4
  export interface AssetTransformOperation {
5
- type: 'crop' | 'resize' | 'rotate' | 'blur' | 'radius' | 'dpr' | 'background' | 'overlay' | 'trim' | 'fps' | 'timestamp';
5
+ type: 'crop' | 'resize' | 'rotate' | 'blur' | 'radius' | 'dpr' | 'background' | 'overlay' | 'trim' | 'fps' | 'timestamp' | 'remove_background' | 'smart_crop';
6
+ focus?: 'attention' | 'entropy';
6
7
  mode?: 'explicit' | 'fit' | 'fill' | 'pad';
7
8
  gravity?: 'northwest' | 'north' | 'northeast' | 'west' | 'centre' | 'east' | 'southwest' | 'south' | 'southeast';
8
9
  width?: number;
@@ -39,6 +40,19 @@ export type AssetTransformMaterializeInput = {
39
40
  preset: string;
40
41
  definition?: never;
41
42
  };
43
+ export interface AssetTransformEstimateInput {
44
+ version_id: string;
45
+ definition: AssetTransformDefinition;
46
+ }
47
+ export interface AssetTransformEstimate {
48
+ cost_micros: number;
49
+ currency: string;
50
+ steps: Array<{
51
+ index: number;
52
+ type: AssetTransformOperation['type'];
53
+ cost_micros: number;
54
+ }>;
55
+ }
42
56
  export interface AssetDerivedAsset {
43
57
  id: string;
44
58
  asset_id: string;
@@ -257,3 +257,38 @@ export interface AssetRenderingInfo {
257
257
  sets: AssetRenderSet[];
258
258
  deliveries: Record<string, AssetPublicationDelivery>;
259
259
  }
260
+ export interface AssetReferrerUsage {
261
+ window_days: number;
262
+ referrers: Array<{
263
+ host: string;
264
+ requests: number;
265
+ }>;
266
+ }
267
+ export interface AssetHoldDetail {
268
+ kind: 'scan' | 'content' | 'policy';
269
+ finding: string;
270
+ explanation: string;
271
+ explained_by: 'stackie' | 'scan_result' | 'content_check';
272
+ version_id: string;
273
+ upload: {
274
+ window_minutes: number;
275
+ files: number;
276
+ held: Array<{
277
+ id: string;
278
+ name: string;
279
+ }>;
280
+ };
281
+ same_content: number;
282
+ }
283
+ export interface AssetReuploadRequestInput {
284
+ email?: string;
285
+ message?: string;
286
+ }
287
+ export interface AssetReuploadRequest {
288
+ id: string;
289
+ email: string;
290
+ status: 'sent' | 'completed' | 'expired' | 'revoked';
291
+ expires_at: string;
292
+ created_at: string;
293
+ completed_at?: string;
294
+ }
package/dist/assets.d.ts CHANGED
@@ -2,8 +2,9 @@ import { AssetDAMClient } from './assets-dam.js';
2
2
  import { AssetVideoClient } from './assets-video.js';
3
3
  import type { StackShift } from './client.js';
4
4
  import { AssetConnectionsClient, AssetMigrationsClient, AssetStorageClient, AssetTextClient, AssetUploadCapabilitiesClient } from './assets-platform.js';
5
+ import type { AssetHoldDetail, AssetReferrerUsage, AssetReuploadRequest, AssetReuploadRequestInput } from './assets-dam-types.js';
5
6
  import { AssetWorkflowsClient } from './asset-workflows.js';
6
- import type { AssetDerivedAsset, AssetImageGenerationInput, AssetTransformDefinition, AssetTransformMaterializeInput } from './asset-media-v2.js';
7
+ import type { AssetDerivedAsset, AssetImageGenerationInput, AssetTransformDefinition, AssetTransformEstimate, AssetTransformEstimateInput, AssetTransformMaterializeInput } from './asset-media-v2.js';
7
8
  import type { Asset, AssetBucket, AssetBucketInput, AssetAIAccountConfig, AssetPatchInput, AssetAIAnnotation, AssetManualDescriptionInput, AssetCustomDomain, AssetEvent, AssetJob, AssetJobSubmission, AssetLifecycleRule, AssetUsageSummary, AssetWebhook, AssetWebhookDelivery, AssetAIInfo, AssetCollection, AssetContentPolicy, AssetNamedTransformInput, AssetListOptions, AssetListResult, AssetSavedSearch, AssetTranscript, AssetUploadProgressCallbacks, AssetVersion, AssetSignedUploadUrl, AssetSignedUploadUrlOptions, AssetSignedTransformOptions, AssetSignedUrl, AssetSignedUrlOptions, AssetTransformOptions, AssetTransformPreset, AssetUploadOptions } from './types.js';
8
9
  export declare const assetTransformPresets: AssetTransformPreset[];
9
10
  export declare function getAssetTransformPreset(name: string): AssetTransformPreset | undefined;
@@ -66,6 +67,12 @@ export declare class AssetsClient {
66
67
  requestTranscript(assetId: string, idempotencyKey?: string): Promise<AssetJobSubmission>;
67
68
  requestSmartCrop(assetId: string, idempotencyKey?: string): Promise<AssetJobSubmission>;
68
69
  requestBackgroundRemoval(assetId: string, idempotencyKey?: string): Promise<AssetJobSubmission>;
70
+ usage(assetId: string): Promise<AssetReferrerUsage>;
71
+ hold(assetId: string): Promise<AssetHoldDetail>;
72
+ createReuploadRequest(assetId: string, input?: AssetReuploadRequestInput): Promise<AssetReuploadRequest>;
73
+ reuploadRequests(assetId: string): Promise<{
74
+ requests: AssetReuploadRequest[];
75
+ }>;
69
76
  versions(assetId: string): Promise<{
70
77
  versions: AssetVersion[];
71
78
  }>;
@@ -110,6 +117,7 @@ export declare class AssetsClient {
110
117
  updatePolicy(policy: AssetContentPolicy): Promise<AssetContentPolicy>;
111
118
  createTransformation(input: AssetNamedTransformInput): Promise<unknown>;
112
119
  createTransformationV2(name: string, definition: AssetTransformDefinition, eager?: boolean): Promise<unknown>;
120
+ estimateTransform(assetId: string, input: AssetTransformEstimateInput): Promise<AssetTransformEstimate>;
113
121
  materializeTransform(assetId: string, input: AssetTransformMaterializeInput, idempotencyKey?: string): Promise<AssetJobSubmission>;
114
122
  derivatives(assetId: string): Promise<{
115
123
  derivatives: AssetDerivedAsset[];
package/dist/assets.js CHANGED
@@ -291,6 +291,20 @@ export class AssetsClient {
291
291
  requestBackgroundRemoval(assetId, idempotencyKey) {
292
292
  return this.requestAssetJob(`/assets/${encodeURIComponent(assetId)}/background-remove`, idempotencyKey);
293
293
  }
294
+ usage(assetId) {
295
+ return this.client.request(`/assets/${encodeURIComponent(assetId)}/usage`);
296
+ }
297
+ hold(assetId) {
298
+ return this.client.request(`/assets/${encodeURIComponent(assetId)}/hold`);
299
+ }
300
+ createReuploadRequest(assetId, input = {}) {
301
+ return this.client.request(`/assets/${encodeURIComponent(assetId)}/reupload-requests`, {
302
+ method: 'POST', body: input,
303
+ });
304
+ }
305
+ reuploadRequests(assetId) {
306
+ return this.client.request(`/assets/${encodeURIComponent(assetId)}/reupload-requests`);
307
+ }
294
308
  versions(assetId) {
295
309
  return this.client.request(`/assets/${encodeURIComponent(assetId)}/versions`);
296
310
  }
@@ -350,6 +364,11 @@ export class AssetsClient {
350
364
  method: 'POST', body: { name, definition, eager },
351
365
  });
352
366
  }
367
+ estimateTransform(assetId, input) {
368
+ return this.client.request(`/assets/${encodeURIComponent(assetId)}/transforms/estimate`, {
369
+ method: 'POST', body: input,
370
+ });
371
+ }
353
372
  materializeTransform(assetId, input, idempotencyKey) {
354
373
  return this.client.request(`/assets/${encodeURIComponent(assetId)}/transforms`, {
355
374
  method: 'POST', body: input,
package/dist/client.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AICreditsClient } from './ai-credits.js';
2
2
  import { AssetsClient } from './assets.js';
3
3
  import { MailClient } from './mail.js';
4
+ import { PartnerClient } from './partner.js';
4
5
  import { ProjectsClient } from './projects.js';
5
6
  import { WorkloadSecurityClient } from './workload-security.js';
6
7
  import type { StackShiftOptions } from './types.js';
@@ -14,6 +15,7 @@ export declare class StackShift {
14
15
  readonly projects: ProjectsClient;
15
16
  readonly assets: AssetsClient;
16
17
  readonly mail: MailClient;
18
+ readonly partner: PartnerClient;
17
19
  readonly workloadSecurity: WorkloadSecurityClient;
18
20
  private readonly fetcher;
19
21
  constructor(options?: StackShiftOptions);
package/dist/client.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { AICreditsClient } from './ai-credits.js';
2
2
  import { AssetsClient } from './assets.js';
3
3
  import { MailClient } from './mail.js';
4
+ import { PartnerClient } from './partner.js';
4
5
  import { ProjectsClient } from './projects.js';
5
6
  import { WorkloadSecurityClient } from './workload-security.js';
6
7
  const defaultBaseUrl = 'https://api.stackshift.cloud/api/v1';
@@ -16,6 +17,7 @@ export class StackShift {
16
17
  projects;
17
18
  assets;
18
19
  mail;
20
+ partner;
19
21
  workloadSecurity;
20
22
  fetcher;
21
23
  constructor(options = {}) {
@@ -33,6 +35,7 @@ export class StackShift {
33
35
  this.projects = new ProjectsClient(this);
34
36
  this.assets = new AssetsClient(this);
35
37
  this.mail = new MailClient(this);
38
+ this.partner = new PartnerClient(this);
36
39
  this.workloadSecurity = new WorkloadSecurityClient(this);
37
40
  }
38
41
  async request(path, init = {}) {
package/dist/index.d.ts CHANGED
@@ -16,7 +16,7 @@ export type { ArtDirectionSource, ResponsiveImageDescriptor, ResponsiveImageOpti
16
16
  export { assetContractOperations } from './generated/assets-contract.js';
17
17
  export type { AssetAPIScope, AssetContractOperation, AssetOperationId } from './generated/assets-contract.js';
18
18
  export { MailBouncesClient, MailClient, MailDomainsClient, MailEventsClient, MailLimitsClient, MailMessagesClient, MailScheduledClient, MailBatchClient, MailInboundClient, MailAnalyticsClient, MailOtpChallengesClient, MailOtpClient, MailReputationClient, MailReputationEventsClient, MailSuppressionsClient, MailTemplatesClient, MailWebhooksClient, MailStreamsClient, MailAudiencesClient, MailCampaignsClient, } from './mail.js';
19
- export type { MailAudience, MailAudienceMember, MailAudienceMemberImport, MailCampaign } from './mail-campaigns.js';
19
+ export type { MailAudience, MailAudienceMember, MailAudienceMemberImport, MailBrandFilterOptions, MailCampaign } from './mail-campaigns.js';
20
20
  export { MailExportsClient } from './mail-exports.js';
21
21
  export type { MailExport, MailExportCreateInput } from './mail-exports.js';
22
22
  export { MailboxAliasesClient, MailboxDomainsClient, MailboxGroupsClient, MailboxImportsClient, MailboxRoutesClient, MailboxesClient } from './mail-mailboxes.js';
@@ -29,7 +29,7 @@ export type { Asset, AssetAIAnnotation, AssetAIInfo, AssetManualDescriptionInput
29
29
  export type { MailBounce, MailBounceListOptions, MailBounceListResult, MailBounceType, MailSuppression, MailSuppressionCreateInput, MailSuppressionListOptions, MailSuppressionListResult, MailSuppressionReason, MailSuppressionSource, } from './mail-delivery-types.js';
30
30
  export type { MailOtpChallenge, MailOtpChallengeListOptions, MailOtpChallengeListResult, MailOtpSendInput, MailOtpSendResponse, MailOtpStatus, MailOtpVerifyInput, MailOtpVerifyResponse, } from './mail-otp-types.js';
31
31
  export type { MailSendTemplateInput, MailSendTemplateResponse, MailTemplate, MailTemplateCreateInput, MailTemplateDetail, MailTemplateListOptions, MailTemplateListResult, MailTemplatePreview, MailTemplatePreviewInput, MailTemplateStatus, MailTemplateTestSendInput, MailTemplateTestSendResponse, MailTemplateUpdateInput, MailTemplateVersion, } from './mail-template-types.js';
32
- export type { MailEvent, MailEventListOptions, MailEventListResult, MailEventType, MailTimelineItem, MailWebhook, MailWebhookCreateInput, MailWebhookCreateResponse, MailWebhookDelivery, MailWebhookDeliveryAttempt, MailWebhookDeliveryDetail, MailWebhookDeliveryListOptions, MailWebhookListOptions, MailWebhookListResult, MailWebhookUpdateInput, MailWebhookReplay, MailWebhookReplayInput, } from './mail-webhook-types.js';
32
+ export type { MailEvent, MailEventListOptions, MailEventListResult, MailEventType, MailTimelineItem, MailWebhook, MailWebhookCreateInput, MailWebhookCreateResponse, MailWebhookDelivery, MailWebhookDeliveryAttempt, MailWebhookDeliveryDetail, MailWebhookDeliveryListItem, MailWebhookDeliveryListOptions, MailWebhookDeliveryMerchant, MailWebhookDetail, MailWebhookDiagnosis, MailWebhookDiagnosisResult, MailWebhookListOptions, MailWebhookListResult, MailWebhookUpdateInput, MailWebhookReplay, MailWebhookReplayInput, MailWebhookWaitingHighlight, MailWebhookWaitingSummary, } from './mail-webhook-types.js';
33
33
  export type { MailMessageStream, MailMessageStreamCreateInput, MailMessageStreamListResult } from './mail-streams.js';
34
34
  export type { MailDomainReputation, MailLimits, MailManualReviewStatus, MailReputation, MailReputationEvent, MailReputationEventListOptions, MailReputationEventListResult, MailReputationEventSeverity, MailReputationStatus, MailReputationTier, MailReputationWorkspace, } from './mail-reputation-types.js';
35
35
  export type { MailAnalytics, MailAnalyticsRateCohort, MailAnalyticsInput, MailAttachmentInput, MailBatch, MailBatchItem, MailBatchSendInput, MailBatchTemplateInput, MailInboundDomain, MailInboundMessage, MailScheduledCreateInput, MailScheduledMessage, } from './mail-advanced-types.js';
@@ -45,6 +45,8 @@ export * from './mail-brands.js';
45
45
  export * from './mail-billing.js';
46
46
  export * from './mail-migration.js';
47
47
  export * from './mail-marketing.js';
48
+ export { PartnerClient } from './partner.js';
49
+ export type * from './partner.js';
48
50
  export { AICreditsClient } from './ai-credits.js';
49
51
  export type * from './ai-credits.js';
50
52
  export * from './support-action-types.js';
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ export * from './mail-brands.js';
19
19
  export * from './mail-billing.js';
20
20
  export * from './mail-migration.js';
21
21
  export * from './mail-marketing.js';
22
+ export { PartnerClient } from './partner.js';
22
23
  export { AICreditsClient } from './ai-credits.js';
23
24
  export * from './support-action-types.js';
24
25
  export * from './support-actions.js';
@@ -26,6 +26,17 @@ export interface MailBillingSummary {
26
26
  revision: number;
27
27
  };
28
28
  }
29
+ export interface MailBillingPeriodUsage {
30
+ period: string;
31
+ planSlug?: string;
32
+ currency: 'NGN';
33
+ periodStart: string;
34
+ periodEnd: string;
35
+ monthlyPriceKobo: number;
36
+ included: number;
37
+ used: number;
38
+ spentKobo: number;
39
+ }
29
40
  export interface MailCampaignEstimate extends MailBillingSummary {
30
41
  recipientCount: number;
31
42
  requiredCreditKobo: number;
@@ -35,4 +46,5 @@ export declare class MailBillingClient {
35
46
  private readonly client;
36
47
  constructor(client: StackShift);
37
48
  summary(): Promise<MailBillingSummary>;
49
+ periodUsage(period: string): Promise<MailBillingPeriodUsage>;
38
50
  }
@@ -4,4 +4,7 @@ export class MailBillingClient {
4
4
  this.client = client;
5
5
  }
6
6
  summary() { return this.client.mailRequest('/mail/billing'); }
7
+ periodUsage(period) {
8
+ return this.client.mailRequest(`/mail/billing?period=${encodeURIComponent(period)}`);
9
+ }
7
10
  }
@@ -10,22 +10,35 @@ export interface MailBrandFields {
10
10
  website?: string;
11
11
  supportEmail?: string;
12
12
  editableFields?: string[];
13
+ merchantRef?: string;
13
14
  }
14
15
  export interface MailBrand extends MailBrandFields {
15
16
  id: string;
16
17
  workspaceId: string;
17
18
  mode: MailMode;
18
19
  status: 'active' | 'archived';
20
+ sendingPausedAt: string | null;
21
+ sendingPauseReason: string;
22
+ suspendedAt: string | null;
19
23
  revision: number;
20
24
  createdAt: string;
21
25
  updatedAt: string;
22
26
  }
27
+ export interface MailBrandWarmup {
28
+ day: number;
29
+ totalDays: number;
30
+ marketingUnlocked: boolean;
31
+ status: 'new' | 'warming' | 'trusted';
32
+ }
33
+ export interface MailBrandListItem extends MailBrand {
34
+ warmup: MailBrandWarmup | null;
35
+ }
23
36
  export declare class MailBrandsClient {
24
37
  private readonly client;
25
38
  constructor(client: StackShift);
26
39
  create(input: MailBrandFields): Promise<MailBrand>;
27
40
  list(): Promise<{
28
- data: MailBrand[];
41
+ data: MailBrandListItem[];
29
42
  }>;
30
43
  get(id: string): Promise<MailBrand>;
31
44
  update(id: string, input: MailBrandFields & {
@@ -40,6 +40,9 @@ export interface MailAudienceMemberImport {
40
40
  consentIp?: string;
41
41
  attributes?: Record<string, string>;
42
42
  }
43
+ export interface MailBrandFilterOptions {
44
+ brandId?: string;
45
+ }
43
46
  export interface MailCampaignContent {
44
47
  subject: string;
45
48
  previewText?: string;
@@ -95,7 +98,7 @@ export declare class MailAudiencesClient {
95
98
  name: string;
96
99
  description?: string;
97
100
  }): Promise<MailAudience>;
98
- list(): Promise<{
101
+ list(options?: MailBrandFilterOptions): Promise<{
99
102
  data: MailAudience[];
100
103
  }>;
101
104
  get(id: string): Promise<MailAudience>;
@@ -116,7 +119,7 @@ export declare class MailCampaignsClient {
116
119
  private readonly client;
117
120
  constructor(client: StackShift);
118
121
  create(input: MailCampaignInput): Promise<MailCampaign>;
119
- list(): Promise<{
122
+ list(options?: MailBrandFilterOptions): Promise<{
120
123
  data: MailCampaign[];
121
124
  }>;
122
125
  get(id: string): Promise<MailCampaign>;
@@ -6,8 +6,9 @@ export class MailAudiencesClient {
6
6
  create(input) {
7
7
  return this.client.mailRequest('/mail/audiences', { method: 'POST', body: input });
8
8
  }
9
- list() {
10
- return this.client.mailRequest('/mail/audiences');
9
+ list(options = {}) {
10
+ const query = options.brandId ? `?brandId=${encodeURIComponent(options.brandId)}` : '';
11
+ return this.client.mailRequest(`/mail/audiences${query}`);
11
12
  }
12
13
  get(id) {
13
14
  return this.client.mailRequest(`/mail/audiences/${encodeURIComponent(id)}`);
@@ -39,8 +40,9 @@ export class MailCampaignsClient {
39
40
  create(input) {
40
41
  return this.client.mailRequest('/mail/campaigns', { method: 'POST', body: input });
41
42
  }
42
- list() {
43
- return this.client.mailRequest('/mail/campaigns');
43
+ list(options = {}) {
44
+ const query = options.brandId ? `?brandId=${encodeURIComponent(options.brandId)}` : '';
45
+ return this.client.mailRequest(`/mail/campaigns${query}`);
44
46
  }
45
47
  get(id) {
46
48
  return this.client.mailRequest(`/mail/campaigns/${encodeURIComponent(id)}`);
@@ -14,6 +14,7 @@ export interface MailSuppression {
14
14
  export interface MailSuppressionListOptions {
15
15
  email?: string;
16
16
  reason?: MailSuppressionReason;
17
+ brandId?: string;
17
18
  limit?: number;
18
19
  cursor?: string;
19
20
  }
@@ -1,5 +1,5 @@
1
1
  import type { StackShift } from './client.js';
2
- import type { MailEvent, MailEventListOptions, MailEventListResult, MailTimelineItem, MailWebhook, MailWebhookCreateInput, MailWebhookCreateResponse, MailWebhookDelivery, MailWebhookDeliveryDetail, MailWebhookDeliveryListOptions, MailWebhookListOptions, MailWebhookListResult, MailWebhookReplay, MailWebhookReplayInput, MailWebhookUpdateInput } from './mail-webhook-types.js';
2
+ import type { MailEvent, MailEventListOptions, MailEventListResult, MailTimelineItem, MailWebhook, MailWebhookCreateInput, MailWebhookCreateResponse, MailWebhookDelivery, MailWebhookDeliveryDetail, MailWebhookDeliveryListItem, MailWebhookDeliveryListOptions, MailWebhookDetail, MailWebhookDiagnosisResult, MailWebhookListOptions, MailWebhookListResult, MailWebhookReplay, MailWebhookReplayInput, MailWebhookUpdateInput } from './mail-webhook-types.js';
3
3
  export declare class MailEventsClient {
4
4
  private readonly client;
5
5
  constructor(client: StackShift);
@@ -11,14 +11,19 @@ export declare class MailWebhooksClient {
11
11
  constructor(client: StackShift);
12
12
  create(input: MailWebhookCreateInput): Promise<MailWebhookCreateResponse>;
13
13
  list(options?: MailWebhookListOptions): Promise<MailWebhookListResult>;
14
- get(webhookId: string): Promise<MailWebhook>;
14
+ get(webhookId: string): Promise<MailWebhookDetail>;
15
15
  update(webhookId: string, input: MailWebhookUpdateInput): Promise<MailWebhook>;
16
16
  rotateSecret(webhookId: string): Promise<{
17
17
  secret: string;
18
18
  }>;
19
+ revealSecret(webhookId: string): Promise<{
20
+ secret: string;
21
+ }>;
22
+ diagnosis(webhookId: string): Promise<MailWebhookDiagnosisResult>;
23
+ diagnose(webhookId: string): Promise<MailWebhookDiagnosisResult>;
19
24
  delete(webhookId: string): Promise<void>;
20
25
  deliveries(webhookId: string, options?: MailWebhookDeliveryListOptions): Promise<{
21
- data: MailWebhookDelivery[];
26
+ data: MailWebhookDeliveryListItem[];
22
27
  nextCursor?: string | null;
23
28
  }>;
24
29
  getDelivery(deliveryId: string): Promise<MailWebhookDeliveryDetail>;
@@ -39,6 +39,19 @@ export class MailWebhooksClient {
39
39
  method: 'POST',
40
40
  });
41
41
  }
42
+ revealSecret(webhookId) {
43
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}/reveal-secret`, {
44
+ method: 'POST',
45
+ });
46
+ }
47
+ diagnosis(webhookId) {
48
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}/diagnosis`);
49
+ }
50
+ diagnose(webhookId) {
51
+ return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}/diagnosis`, {
52
+ method: 'POST',
53
+ });
54
+ }
42
55
  delete(webhookId) {
43
56
  return this.client.mailRequest(`/mail/webhooks/${encodeURIComponent(webhookId)}`, {
44
57
  method: 'DELETE',
@@ -1,6 +1,14 @@
1
1
  import type { MailMode } from './mail-simulation.js';
2
2
  import type { JsonValue } from './types.js';
3
- export type MailEventType = 'mail.message.opened' | 'mail.message.clicked' | 'mail.message.accepted' | 'mail.message.queued' | 'mail.message.sending' | 'mail.message.mta_accepted' | 'mail.delivery.delayed' | 'mail.delivery.delivered' | 'mail.message.failed' | 'mail.message.bounced' | 'mail.message.suppressed' | 'mail.message.complained' | 'mail.suppression.created' | 'mail.suppression.deleted' | 'mail.otp.created' | 'mail.otp.sent' | 'mail.otp.verified' | 'mail.otp.failed_attempt' | 'mail.otp.failed' | 'mail.otp.expired' | 'mail.otp.canceled' | 'mail.template.created' | 'mail.template.updated' | 'mail.template.deleted' | 'mail.template.version.created' | 'mail.template.test_queued' | 'mail.domain.created' | 'mail.domain.verified' | 'mail.domain.failed' | 'mail.domain.deleted' | 'mail.webhook.created' | 'mail.webhook.updated' | 'mail.webhook.disabled' | 'mail.webhook.delivery.succeeded' | 'mail.webhook.delivery.failed' | 'mail.audience.created' | 'mail.audience.members.imported' | 'mail.campaign.created' | 'mail.campaign.queued';
3
+ export type MailEventType = 'mail.message.opened' | 'mail.message.clicked' | 'mail.message.accepted' | 'mail.message.queued' | 'mail.message.sending' | 'mail.message.mta_accepted' | 'mail.delivery.delayed' | 'mail.delivery.delivered' | 'mail.message.failed' | 'mail.message.bounced' | 'mail.message.suppressed' | 'mail.message.complained' | 'mail.suppression.created' | 'mail.suppression.deleted' | 'mail.otp.created' | 'mail.otp.sent' | 'mail.otp.verified' | 'mail.otp.failed_attempt' | 'mail.otp.failed' | 'mail.otp.expired' | 'mail.otp.canceled' | 'mail.template.created' | 'mail.template.updated' | 'mail.template.deleted' | 'mail.template.version.created' | 'mail.template.test_queued' | 'mail.domain.created' | 'mail.domain.verified' | 'mail.domain.failed' | 'mail.domain.deleted' | 'mail.webhook.created' | 'mail.webhook.updated' | 'mail.webhook.disabled' | 'mail.webhook.delivery.succeeded' | 'mail.webhook.delivery.failed' | 'mail.audience.created' | 'mail.audience.members.imported' | 'mail.campaign.created' | 'mail.campaign.queued' | 'mail.campaign.stopped' | 'partner.domain.registered' | 'partner.domain.failed' | 'partner.domain.dns_verified' | 'partner.brand.ready' | 'partner.warmup.progress' | 'partner.brand.warning' | 'partner.brand.paused' | 'partner.brand.resumed' | 'partner.brand.bounced' | 'partner.brand.complained' | 'partner.domain.renewal_due' | 'partner.domain.renewed' | 'partner.domain.renewal_failed';
4
+ export interface MailCampaignStoppedEvent {
5
+ campaignId: string;
6
+ brandId: string;
7
+ reason: 'sender_paused';
8
+ pauseReason: 'complaint_rate' | 'bounce_rate' | 'partner_suspended' | string;
9
+ pausedSince: string;
10
+ message: string;
11
+ }
4
12
  export interface MailEvent {
5
13
  mode?: MailMode;
6
14
  id: string;
@@ -43,6 +51,20 @@ export interface MailWebhook {
43
51
  lastFailureAt?: string | null;
44
52
  createdAt: string;
45
53
  }
54
+ export interface MailWebhookWaitingHighlight {
55
+ type: string;
56
+ shop: string;
57
+ }
58
+ export interface MailWebhookWaitingSummary {
59
+ count: number;
60
+ capped: boolean;
61
+ oldestAt: string;
62
+ merchantUpdates: number;
63
+ highlights: MailWebhookWaitingHighlight[];
64
+ }
65
+ export interface MailWebhookDetail extends MailWebhook {
66
+ waitingSummary: MailWebhookWaitingSummary | null;
67
+ }
46
68
  export interface MailWebhookCreateInput {
47
69
  url: string;
48
70
  description?: string;
@@ -80,6 +102,23 @@ export interface MailWebhookDelivery {
80
102
  createdAt: string;
81
103
  completedAt?: string | null;
82
104
  }
105
+ export interface MailWebhookDeliveryMerchant {
106
+ partnerDomainId: string;
107
+ merchantRef: string;
108
+ shop: string;
109
+ }
110
+ export interface MailWebhookDeliveryListItem extends MailWebhookDelivery {
111
+ durationMs: number | null;
112
+ merchant: MailWebhookDeliveryMerchant | null;
113
+ }
114
+ export interface MailWebhookDiagnosis {
115
+ checkedAt: string;
116
+ repliesRead: number;
117
+ summary: string;
118
+ }
119
+ export interface MailWebhookDiagnosisResult {
120
+ diagnosis: MailWebhookDiagnosis | null;
121
+ }
83
122
  export interface MailWebhookDeliveryAttempt {
84
123
  id: string;
85
124
  attemptNumber: number;
package/dist/mail.js CHANGED
@@ -262,6 +262,7 @@ export class MailSuppressionsClient {
262
262
  const query = new URLSearchParams();
263
263
  append(query, 'email', options.email);
264
264
  append(query, 'reason', options.reason);
265
+ append(query, 'brandId', options.brandId);
265
266
  append(query, 'limit', options.limit);
266
267
  append(query, 'cursor', options.cursor);
267
268
  const suffix = query.toString();
@@ -0,0 +1,369 @@
1
+ import type { StackShift } from './client.js';
2
+ import type { MailBrand } from './mail-brands.js';
3
+ import type { JsonValue } from './types.js';
4
+ export type PartnerDomainState = 'registering' | 'mail_setup' | 'verifying' | 'replies' | 'brand_setup' | 'ready' | 'failed';
5
+ export type PartnerRepliesMode = 'forward' | 'mailbox';
6
+ export interface PartnerAccount {
7
+ userId: string;
8
+ name: string;
9
+ status: 'active' | 'suspended' | string;
10
+ complaintPauseRate: number;
11
+ bouncePauseRate: number;
12
+ dedicatedPoolName: string | null;
13
+ dailyPurchaseLimit: number;
14
+ createdAt: string;
15
+ updatedAt: string;
16
+ }
17
+ export interface PartnerWalletBalance {
18
+ currency: string;
19
+ balance_minor: number;
20
+ held_minor: number;
21
+ disputed_minor: number;
22
+ available_minor: number;
23
+ }
24
+ export interface PartnerLimits {
25
+ maxComplaintPauseRate: number;
26
+ maxBouncePauseRate: number;
27
+ minimumRecipients: number;
28
+ windowDays: number;
29
+ shortWindowHours: number;
30
+ dailyPurchaseLimit: number;
31
+ warningFraction: number;
32
+ merchantSharePercent: number;
33
+ merchantCount: number;
34
+ dailySendingLimit: number;
35
+ hourlySendingLimit: number;
36
+ }
37
+ export interface PartnerOverview {
38
+ account: PartnerAccount;
39
+ wallet: PartnerWalletBalance[];
40
+ webhookEvents: string[];
41
+ limits: PartnerLimits;
42
+ }
43
+ export interface PartnerSettingsInput {
44
+ complaintPauseRate: number;
45
+ bouncePauseRate: number;
46
+ }
47
+ export interface PartnerRegistrant {
48
+ first_name: string;
49
+ last_name: string;
50
+ organization?: string;
51
+ email: string;
52
+ phone: string;
53
+ address: string;
54
+ city: string;
55
+ state: string;
56
+ postal_code: string;
57
+ country: string;
58
+ }
59
+ export interface PartnerBrandInput {
60
+ name: string;
61
+ fromLocalPart?: string;
62
+ postalAddress: string;
63
+ website?: string;
64
+ supportEmail?: string;
65
+ }
66
+ export interface PartnerRepliesInput {
67
+ mode: PartnerRepliesMode;
68
+ forwardTo?: string;
69
+ mailboxOwnerEmail?: string;
70
+ mailboxPlan?: string;
71
+ }
72
+ export interface PartnerDomainPurchaseInput {
73
+ domain: string;
74
+ years: number;
75
+ currency?: 'NGN' | 'USD';
76
+ merchantRef: string;
77
+ registrant: PartnerRegistrant;
78
+ brand: PartnerBrandInput;
79
+ replies: PartnerRepliesInput;
80
+ }
81
+ export interface PartnerPurchaseOptions {
82
+ idempotencyKey: string;
83
+ }
84
+ export type PartnerFailureCode = 'nameservers_changed' | 'dns_not_visible' | 'wallet_short' | 'registry_taken' | 'registration_rejected' | 'registration_timed_out' | 'purchase_interrupted' | 'mailbox_unavailable' | 'mail_setup_rejected' | 'dns_provider_error' | 'registration_mismatch' | 'sending_domains_missing' | 'internal_retrying';
85
+ export interface PartnerFailureFact {
86
+ label: string;
87
+ value: string;
88
+ tone: 'bad' | 'ok' | 'neutral';
89
+ at: string | null;
90
+ }
91
+ export type PartnerFailureFix = {
92
+ label: string;
93
+ action: 'restore_nameservers';
94
+ } | {
95
+ label: string;
96
+ href: string;
97
+ };
98
+ export interface PartnerFailure {
99
+ code: PartnerFailureCode;
100
+ title: string;
101
+ headline: string;
102
+ explanation: string;
103
+ since: string | null;
104
+ facts: PartnerFailureFact[];
105
+ data: Record<string, JsonValue>;
106
+ fix: PartnerFailureFix | null;
107
+ canRetry: boolean;
108
+ }
109
+ export interface PartnerDiagnosis {
110
+ checkedAt: string;
111
+ summary: string;
112
+ }
113
+ export interface PartnerPause {
114
+ reason: 'complaint_rate' | 'bounce_rate';
115
+ rate: number;
116
+ limit: number;
117
+ window: 'last_7_days' | 'last_24_hours';
118
+ campaignId: string | null;
119
+ campaignName: string | null;
120
+ listId: string | null;
121
+ listName: string | null;
122
+ listImportedAt: string | null;
123
+ listShare: number | null;
124
+ recoversAt: string | null;
125
+ }
126
+ export interface PartnerWaitingFor {
127
+ kind: 'wallet';
128
+ currency: string;
129
+ requiredMinor: number;
130
+ availableMinor: number;
131
+ }
132
+ export interface PartnerRefund {
133
+ amountMinor: number;
134
+ currency: string;
135
+ at: string;
136
+ }
137
+ export interface PartnerMerchantDomain {
138
+ id: string;
139
+ partnerUserId: string;
140
+ merchantRef: string;
141
+ domain: string;
142
+ years: number;
143
+ domainOrderId: string | null;
144
+ registeredDomainId: string | null;
145
+ mailDomainId: string | null;
146
+ brandId: string | null;
147
+ mailboxDomainId: string | null;
148
+ mailboxId: string | null;
149
+ brand: PartnerBrandInput;
150
+ registrant: PartnerRegistrant;
151
+ replies: PartnerRepliesInput;
152
+ state: PartnerDomainState;
153
+ failedState: PartnerDomainState | null;
154
+ lastError: string;
155
+ attempts: number;
156
+ nextAttemptAt: string;
157
+ lastAttemptAt: string | null;
158
+ waitingFor: PartnerWaitingFor | null;
159
+ warmupDay: number;
160
+ healthWarnedAt: string | null;
161
+ transferredOutAt: string | null;
162
+ amountMinor: number;
163
+ currency: string;
164
+ walletReference: string;
165
+ createdAt: string;
166
+ updatedAt: string;
167
+ expiryDate: string | null;
168
+ brandPausedAt: string | null;
169
+ brandPauseReason: 'complaint_rate' | 'bounce_rate' | '';
170
+ pause: PartnerPause | null;
171
+ failure: PartnerFailure | null;
172
+ diagnosis: PartnerDiagnosis | null;
173
+ }
174
+ export interface PartnerDomainListOptions {
175
+ merchantRef?: string;
176
+ q?: string;
177
+ attention?: boolean;
178
+ limit?: number;
179
+ offset?: number;
180
+ }
181
+ export interface PartnerWarmupSummary {
182
+ status: string;
183
+ day: number;
184
+ totalDays: number;
185
+ marketingUnlocked: boolean;
186
+ marketingOpensInDays: number;
187
+ }
188
+ export interface PartnerDomainListItem extends PartnerMerchantDomain {
189
+ health: PartnerBrandHealth | null;
190
+ transactionalHealth: PartnerBrandHealth | null;
191
+ refunded: boolean;
192
+ sentByDay: number[];
193
+ warmup: PartnerWarmupSummary | null;
194
+ }
195
+ export interface PartnerDomainList {
196
+ domains: PartnerDomainListItem[];
197
+ total: number;
198
+ attentionTotal: number;
199
+ }
200
+ export interface PartnerSenders {
201
+ marketing: string;
202
+ transactional: string;
203
+ replyTo: string;
204
+ }
205
+ export interface PartnerHealthWindow {
206
+ attempted: number;
207
+ accepted: number;
208
+ bounced: number;
209
+ complained: number;
210
+ bounceRate: number;
211
+ complaintRate: number;
212
+ }
213
+ export interface PartnerBrandHealth extends PartnerHealthWindow {
214
+ last24h: PartnerHealthWindow;
215
+ }
216
+ export interface PartnerWarmup {
217
+ status: string;
218
+ day: number;
219
+ totalDays: number;
220
+ dailyLimit: number;
221
+ marketingDailyLimit: number;
222
+ marketingUnlocked: boolean;
223
+ cleanTransactionalDays: number;
224
+ requiredCleanDays: number;
225
+ firstCampaignCap: number;
226
+ paused: boolean;
227
+ marketingSentToday: number;
228
+ marketingOpensInDays: number;
229
+ }
230
+ export type PartnerRecordPurpose = 'dkim' | 'spf' | 'return_path' | 'dmarc' | 'reply_mx' | 'reply_ownership' | 'mta_sts' | 'mta_sts_policy' | 'tls_reporting';
231
+ export interface PartnerRecord {
232
+ domain: string;
233
+ type: string;
234
+ name: string;
235
+ value: string;
236
+ priority: number | null;
237
+ verified: boolean;
238
+ purpose: PartnerRecordPurpose;
239
+ }
240
+ export interface PartnerDomainView extends PartnerMerchantDomain {
241
+ senders: PartnerSenders;
242
+ brandStatus: MailBrand | null;
243
+ health: PartnerBrandHealth | null;
244
+ transactionalHealth: PartnerBrandHealth | null;
245
+ warmup: PartnerWarmup | null;
246
+ replies: PartnerRepliesInput & {
247
+ mailboxOwnerName: string | null;
248
+ };
249
+ records: PartnerRecord[];
250
+ refunded: boolean;
251
+ refund: PartnerRefund | null;
252
+ webhookDeliveredAt: string | null;
253
+ }
254
+ export interface PartnerTransferOut {
255
+ domain: string;
256
+ authCode: string;
257
+ }
258
+ export interface PartnerUsageOptions {
259
+ from?: string;
260
+ to?: string;
261
+ }
262
+ export interface PartnerBrandUsage {
263
+ partnerDomainId: string;
264
+ merchantRef: string;
265
+ domain: string;
266
+ brandId: string | null;
267
+ brandName: string;
268
+ marketingRecipients: number;
269
+ transactionalRecipients: number;
270
+ domainChargesMinor: number;
271
+ refundedMinor: number;
272
+ currency: string;
273
+ }
274
+ export interface PartnerUsage {
275
+ from: string;
276
+ to: string;
277
+ brands: PartnerBrandUsage[];
278
+ }
279
+ export interface PartnerComplaintSummary {
280
+ complained: number;
281
+ suppressed: number;
282
+ }
283
+ export interface PartnerComplaintSource {
284
+ audienceId: string;
285
+ audienceName: string;
286
+ importedAt: string | null;
287
+ contacts: number;
288
+ neverOpened: number;
289
+ complained: number;
290
+ }
291
+ export interface PartnerBulkSuppressionInput {
292
+ audienceId: string;
293
+ reason: 'never_opened';
294
+ }
295
+ export interface PartnerBulkSuppression {
296
+ id: string;
297
+ audienceId: string;
298
+ reason: 'never_opened';
299
+ suppressed: number;
300
+ }
301
+ export type PartnerRequestKind = 'purchase_limit' | 'dedicated_addresses';
302
+ export interface PartnerRequestInput {
303
+ kind: PartnerRequestKind;
304
+ message?: string;
305
+ }
306
+ export interface PartnerRequest {
307
+ id: string;
308
+ kind: PartnerRequestKind;
309
+ message: string;
310
+ status: 'open' | 'done' | 'declined';
311
+ resolvedAt: string | null;
312
+ createdAt: string;
313
+ updatedAt: string;
314
+ }
315
+ export interface PartnerEventBase {
316
+ partnerDomainId: string;
317
+ merchantRef: string;
318
+ domain: string;
319
+ state: PartnerDomainState;
320
+ brandId?: string;
321
+ }
322
+ export interface PartnerBrandHealthEvent extends PartnerEventBase {
323
+ bounceRate: number;
324
+ complaintRate: number;
325
+ recipients: number;
326
+ last24h: PartnerHealthWindow;
327
+ bounceLimit: number;
328
+ complaintLimit: number;
329
+ reason?: 'complaint_rate' | 'bounce_rate';
330
+ }
331
+ export interface PartnerDomainRenewedEvent extends PartnerEventBase {
332
+ expiryDate: string;
333
+ previousExpiryDate: string;
334
+ }
335
+ export interface PartnerDomainRenewalDueEvent extends PartnerEventBase {
336
+ expiryDate: string;
337
+ autoRenew: boolean;
338
+ }
339
+ export interface PartnerDomainRenewalFailedEvent extends PartnerEventBase {
340
+ expiryDate: string;
341
+ reason: string;
342
+ amountMinor: number;
343
+ currency: string;
344
+ }
345
+ export declare class PartnerClient {
346
+ private readonly client;
347
+ constructor(client: StackShift);
348
+ overview(): Promise<PartnerOverview>;
349
+ updateSettings(input: PartnerSettingsInput): Promise<PartnerAccount>;
350
+ purchaseDomain(input: PartnerDomainPurchaseInput, { idempotencyKey }: PartnerPurchaseOptions): Promise<PartnerMerchantDomain>;
351
+ listDomains(options?: PartnerDomainListOptions): Promise<PartnerDomainList>;
352
+ getDomain(id: string): Promise<PartnerDomainView>;
353
+ retryDomain(id: string): Promise<PartnerMerchantDomain>;
354
+ transferOut(id: string): Promise<PartnerTransferOut>;
355
+ getDiagnosis(id: string): Promise<PartnerDiagnosis>;
356
+ restoreDns(id: string): Promise<PartnerMerchantDomain>;
357
+ resumeBrand(brandId: string): Promise<MailBrand>;
358
+ getComplaints(brandId: string): Promise<PartnerComplaintSummary>;
359
+ listComplaintSources(brandId: string): Promise<PartnerComplaintSource[]>;
360
+ suppressNeverOpened(brandId: string, input: PartnerBulkSuppressionInput): Promise<PartnerBulkSuppression>;
361
+ undoSuppression(brandId: string, bulkId: string): Promise<{
362
+ restored: number;
363
+ }>;
364
+ usage(options?: PartnerUsageOptions): Promise<PartnerUsage>;
365
+ listRequests(): Promise<{
366
+ requests: PartnerRequest[];
367
+ }>;
368
+ createRequest(input: PartnerRequestInput): Promise<PartnerRequest>;
369
+ }
@@ -0,0 +1,70 @@
1
+ export class PartnerClient {
2
+ client;
3
+ constructor(client) {
4
+ this.client = client;
5
+ }
6
+ overview() {
7
+ return this.client.request('/partner');
8
+ }
9
+ updateSettings(input) {
10
+ return this.client.request('/partner/settings', { method: 'PUT', body: input });
11
+ }
12
+ purchaseDomain(input, { idempotencyKey }) {
13
+ return this.client.request('/partner/domains', {
14
+ method: 'POST',
15
+ headers: { 'Idempotency-Key': idempotencyKey },
16
+ body: input,
17
+ });
18
+ }
19
+ listDomains(options = {}) {
20
+ return this.client.request(`/partner/domains${queryString(options)}`);
21
+ }
22
+ getDomain(id) {
23
+ return this.client.request(`/partner/domains/${encodeURIComponent(id)}`);
24
+ }
25
+ retryDomain(id) {
26
+ return this.client.request(`/partner/domains/${encodeURIComponent(id)}/retry`, { method: 'POST' });
27
+ }
28
+ transferOut(id) {
29
+ return this.client.request(`/partner/domains/${encodeURIComponent(id)}/transfer-out`, { method: 'POST' });
30
+ }
31
+ getDiagnosis(id) {
32
+ return this.client.request(`/partner/domains/${encodeURIComponent(id)}/diagnosis`);
33
+ }
34
+ restoreDns(id) {
35
+ return this.client.request(`/partner/domains/${encodeURIComponent(id)}/restore-dns`, { method: 'POST' });
36
+ }
37
+ resumeBrand(brandId) {
38
+ return this.client.request(`/partner/brands/${encodeURIComponent(brandId)}/resume`, { method: 'POST' });
39
+ }
40
+ getComplaints(brandId) {
41
+ return this.client.request(`/partner/brands/${encodeURIComponent(brandId)}/complaints`);
42
+ }
43
+ listComplaintSources(brandId) {
44
+ return this.client.request(`/partner/brands/${encodeURIComponent(brandId)}/complaints/sources`);
45
+ }
46
+ suppressNeverOpened(brandId, input) {
47
+ return this.client.request(`/partner/brands/${encodeURIComponent(brandId)}/suppressions/bulk`, { method: 'POST', body: input });
48
+ }
49
+ undoSuppression(brandId, bulkId) {
50
+ return this.client.request(`/partner/brands/${encodeURIComponent(brandId)}/suppressions/bulk/${encodeURIComponent(bulkId)}/undo`, { method: 'POST' });
51
+ }
52
+ usage(options = {}) {
53
+ return this.client.request(`/partner/usage${queryString(options)}`);
54
+ }
55
+ listRequests() {
56
+ return this.client.request('/partner/requests');
57
+ }
58
+ createRequest(input) {
59
+ return this.client.request('/partner/requests', { method: 'POST', body: input });
60
+ }
61
+ }
62
+ function queryString(options) {
63
+ const query = new URLSearchParams();
64
+ for (const [key, value] of Object.entries(options)) {
65
+ if (value !== undefined)
66
+ query.set(key, String(value));
67
+ }
68
+ const suffix = query.toString();
69
+ return suffix ? `?${suffix}` : '';
70
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackshift-cloud/sdk",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Official JavaScript and TypeScript SDK for StackShift.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -17,7 +17,7 @@
17
17
  ],
18
18
  "scripts": {
19
19
  "build": "tsc -p tsconfig.json",
20
- "test": "npm run build && node test/mail.test.mjs && node test/mail-simulation.test.mjs && node test/mail-platform.test.mjs && node test/mail-webhooks.test.mjs && node test/mail-advanced.test.mjs && node test/mail-tracking.test.mjs && node test/mail-subscribers.test.mjs && node test/mail-exports.test.mjs && node test/mail-mailboxes.test.mjs && node test/mail-diagnostics.test.mjs && node test/assets.test.mjs && node test/assets-platform.test.mjs && node test/assets-video.test.mjs && node test/assets-dam.test.mjs && node test/ai-credits.test.mjs && node --test test/s2-upload.test.mjs",
20
+ "test": "npm run build && node test/mail.test.mjs && node test/mail-simulation.test.mjs && node test/mail-platform.test.mjs && node test/mail-webhooks.test.mjs && node test/mail-advanced.test.mjs && node test/mail-tracking.test.mjs && node test/mail-subscribers.test.mjs && node test/mail-exports.test.mjs && node test/mail-mailboxes.test.mjs && node test/mail-diagnostics.test.mjs && node test/partner.test.mjs && node test/assets.test.mjs && node test/assets-platform.test.mjs && node test/assets-video.test.mjs && node test/assets-dam.test.mjs && node test/ai-credits.test.mjs && node --test test/s2-upload.test.mjs",
21
21
  "test:support-actions": "npm run build && node --test tests/support-actions.test.mjs"
22
22
  },
23
23
  "devDependencies": {