@marlinjai/mail-sdk 0.2.0 → 0.3.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/index.d.mts CHANGED
@@ -42,6 +42,16 @@ interface RequestOpts {
42
42
  * status and request id. An exception thrown here propagates to the caller.
43
43
  */
44
44
  onResponse?: (meta: ResponseMeta) => void;
45
+ /**
46
+ * The person the caller's application is acting for, when the workspace API
47
+ * key is shared by everybody who uses that application: a name or an email
48
+ * address, sent as `ON_BEHALF_OF_HEADER`. The service records it on the
49
+ * audit entry as what the application reported, never verified; it changes
50
+ * nothing about what the key may do. Trimmed; empty is not sent; longer than
51
+ * `ON_BEHALF_OF_MAX_LENGTH` throws before any request is made. Ignored by
52
+ * the service on a dashboard client's calls.
53
+ */
54
+ onBehalfOf?: string;
45
55
  }
46
56
  interface ExecuteArgs<K extends OperationId> {
47
57
  params?: RouteParams<K>;
@@ -68,6 +78,13 @@ interface ExportedFile {
68
78
  }
69
79
  /** The `filename` of a `Content-Disposition` value (the `filename*` UTF-8 form first). */
70
80
  declare function dispositionFilename(value: string | null): string | null;
81
+ interface MultipartArgs<K extends OperationId> {
82
+ params?: RouteParams<K>;
83
+ file: Blob;
84
+ filename?: string;
85
+ /** For routes whose multipart form carries a second JSON field (e.g. `imports.create`). */
86
+ json?: unknown;
87
+ }
71
88
 
72
89
  /**
73
90
  * Namespaced, hand-written wrappers over `execute`/`executeMultipart`. Every
@@ -97,6 +114,8 @@ declare function createNamespaces(config: CoreConfig): {
97
114
  default_locale: string;
98
115
  locales: string[];
99
116
  tracking_enabled: boolean;
117
+ allowed_asset_hosts: string[];
118
+ merge_defaults: Record<string, string | number | boolean>;
100
119
  default_timezone: string | null;
101
120
  };
102
121
  company_id: string | null;
@@ -113,6 +132,8 @@ declare function createNamespaces(config: CoreConfig): {
113
132
  default_locale: string;
114
133
  locales: string[];
115
134
  tracking_enabled: boolean;
135
+ allowed_asset_hosts: string[];
136
+ merge_defaults: Record<string, string | number | boolean>;
116
137
  default_timezone: string | null;
117
138
  };
118
139
  company_id: string | null;
@@ -133,6 +154,8 @@ declare function createNamespaces(config: CoreConfig): {
133
154
  default_locale: string;
134
155
  locales: string[];
135
156
  tracking_enabled: boolean;
157
+ allowed_asset_hosts: string[];
158
+ merge_defaults: Record<string, string | number | boolean>;
136
159
  default_timezone: string | null;
137
160
  };
138
161
  company_id: string | null;
@@ -148,6 +171,8 @@ declare function createNamespaces(config: CoreConfig): {
148
171
  default_locale: string;
149
172
  locales: string[];
150
173
  tracking_enabled: boolean;
174
+ allowed_asset_hosts: string[];
175
+ merge_defaults: Record<string, string | number | boolean>;
151
176
  default_timezone: string | null;
152
177
  };
153
178
  company_id: string | null;
@@ -168,6 +193,8 @@ declare function createNamespaces(config: CoreConfig): {
168
193
  default_locale: string;
169
194
  locales: string[];
170
195
  tracking_enabled: boolean;
196
+ allowed_asset_hosts: string[];
197
+ merge_defaults: Record<string, string | number | boolean>;
171
198
  default_timezone: string | null;
172
199
  };
173
200
  company_id: string | null;
@@ -276,6 +303,8 @@ declare function createNamespaces(config: CoreConfig): {
276
303
  default_locale: string;
277
304
  locales: string[];
278
305
  tracking_enabled: boolean;
306
+ allowed_asset_hosts: string[];
307
+ merge_defaults: Record<string, string | number | boolean>;
279
308
  default_timezone: string | null;
280
309
  };
281
310
  company_id: string | null;
@@ -333,6 +362,7 @@ declare function createNamespaces(config: CoreConfig): {
333
362
  } | {
334
363
  type: "api_key";
335
364
  api_key_id: string;
365
+ on_behalf_of?: string | undefined;
336
366
  } | {
337
367
  type: "system";
338
368
  reason: string;
@@ -609,7 +639,9 @@ declare function createNamespaces(config: CoreConfig): {
609
639
  /**
610
640
  * Copies a remote image into the workspace's assets and answers with the
611
641
  * new asset, whose `url` is the service's own. The workspace setting
612
- * `asset_policy: 'service_only'` accepts only such addresses in a mail.
642
+ * `asset_policy: 'service_only'` accepts only such addresses in a mail,
643
+ * plus any host in `settings.allowed_asset_hosts` (the workspace's own
644
+ * website, typically), whose images need no copy.
613
645
  */
614
646
  import: (body: RouteBody<"assets.import">, opts?: RequestOpts) => Promise<{
615
647
  id: string;
@@ -2077,7 +2109,7 @@ declare function createNamespaces(config: CoreConfig): {
2077
2109
  created_at: string;
2078
2110
  updated_at: string;
2079
2111
  url: string;
2080
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2112
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2081
2113
  enabled: boolean;
2082
2114
  }[];
2083
2115
  next_cursor: string | null;
@@ -2089,7 +2121,7 @@ declare function createNamespaces(config: CoreConfig): {
2089
2121
  created_at: string;
2090
2122
  updated_at: string;
2091
2123
  url: string;
2092
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2124
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2093
2125
  enabled: boolean;
2094
2126
  };
2095
2127
  secret: string;
@@ -2100,7 +2132,7 @@ declare function createNamespaces(config: CoreConfig): {
2100
2132
  created_at: string;
2101
2133
  updated_at: string;
2102
2134
  url: string;
2103
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2135
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2104
2136
  enabled: boolean;
2105
2137
  }>;
2106
2138
  update: (id: string, body: RouteBody<"webhooks.update">, opts?: RequestOpts) => Promise<{
@@ -2109,7 +2141,7 @@ declare function createNamespaces(config: CoreConfig): {
2109
2141
  created_at: string;
2110
2142
  updated_at: string;
2111
2143
  url: string;
2112
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2144
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2113
2145
  enabled: boolean;
2114
2146
  }>;
2115
2147
  delete: (id: string, opts?: RequestOpts) => Promise<{
@@ -2122,7 +2154,7 @@ declare function createNamespaces(config: CoreConfig): {
2122
2154
  created_at: string;
2123
2155
  updated_at: string;
2124
2156
  url: string;
2125
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2157
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2126
2158
  enabled: boolean;
2127
2159
  };
2128
2160
  secret: string;
@@ -2136,7 +2168,7 @@ declare function createNamespaces(config: CoreConfig): {
2136
2168
  last_error: string | null;
2137
2169
  endpoint_id: string;
2138
2170
  event_id: string;
2139
- event_type: "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2171
+ event_type: "template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2140
2172
  last_status_code: number | null;
2141
2173
  next_attempt_at: string | null;
2142
2174
  delivered_at: string | null;
@@ -2151,7 +2183,7 @@ declare function createNamespaces(config: CoreConfig): {
2151
2183
  last_error: string | null;
2152
2184
  endpoint_id: string;
2153
2185
  event_id: string;
2154
- event_type: "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2186
+ event_type: "template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2155
2187
  last_status_code: number | null;
2156
2188
  next_attempt_at: string | null;
2157
2189
  delivered_at: string | null;
@@ -4378,9 +4410,11 @@ interface MailClientOptions extends BaseClientOptions {
4378
4410
  /** A workspace API key (`Authorization: Bearer <key>`), scoped to one workspace and to `full`, `send` or `read`. */
4379
4411
  apiKey: string;
4380
4412
  }
4381
- /** Every namespaced method, plus the two escape hatches: `request` for any operation id, `paginate` for cursor lists. */
4413
+ /** Every namespaced method, plus the escape hatches: `request` for any JSON operation id, `upload` for a multipart one, `paginate` for cursor lists. */
4382
4414
  interface MailClient extends MailNamespaces {
4383
4415
  request<K extends OperationId>(operationId: K, args?: ExecuteArgs<K>, opts?: RequestOpts): Promise<RouteResponse<K>>;
4416
+ /** The multipart routes (`assets.upload`, `imports.create`) by operation id, for a caller that dispatches generically. */
4417
+ upload<K extends OperationId>(operationId: K, args: MultipartArgs<K>, opts?: RequestOpts): Promise<RouteResponse<K>>;
4384
4418
  paginate<K extends PaginatableOperationId>(operationId: K, args?: PaginateArgs<K>, opts?: RequestOpts): AsyncGenerator<PageItem<K>, void, void>;
4385
4419
  /**
4386
4420
  * Checks the service's liveness probe (`HEALTH_PATH`, outside `/v1`, no
@@ -4477,4 +4511,4 @@ declare class MailResponseValidationError extends Error {
4477
4511
  /** A fresh idempotency key, reused across every retry of the same call. */
4478
4512
  declare function generateIdempotencyKey(): string;
4479
4513
 
4480
- export { type BaseClientOptions, type DashboardMailClient, type DashboardMailClientOptions, type DashboardUserContext, type ExecuteArgs, type ExportedFile, MailApiError, type MailClient, type MailClientOptions, MailNetworkError, MailResponseValidationError, MailTimeoutError, type PageItem, type PaginatableOperationId, type PaginateArgs, type RequestOpts, type ResponseMeta, createDashboardMailClient, createMailClient, dispositionFilename, generateIdempotencyKey };
4514
+ export { type BaseClientOptions, type DashboardMailClient, type DashboardMailClientOptions, type DashboardUserContext, type ExecuteArgs, type ExportedFile, MailApiError, type MailClient, type MailClientOptions, MailNetworkError, MailResponseValidationError, MailTimeoutError, type MultipartArgs, type PageItem, type PaginatableOperationId, type PaginateArgs, type RequestOpts, type ResponseMeta, createDashboardMailClient, createMailClient, dispositionFilename, generateIdempotencyKey };
package/dist/index.d.ts CHANGED
@@ -42,6 +42,16 @@ interface RequestOpts {
42
42
  * status and request id. An exception thrown here propagates to the caller.
43
43
  */
44
44
  onResponse?: (meta: ResponseMeta) => void;
45
+ /**
46
+ * The person the caller's application is acting for, when the workspace API
47
+ * key is shared by everybody who uses that application: a name or an email
48
+ * address, sent as `ON_BEHALF_OF_HEADER`. The service records it on the
49
+ * audit entry as what the application reported, never verified; it changes
50
+ * nothing about what the key may do. Trimmed; empty is not sent; longer than
51
+ * `ON_BEHALF_OF_MAX_LENGTH` throws before any request is made. Ignored by
52
+ * the service on a dashboard client's calls.
53
+ */
54
+ onBehalfOf?: string;
45
55
  }
46
56
  interface ExecuteArgs<K extends OperationId> {
47
57
  params?: RouteParams<K>;
@@ -68,6 +78,13 @@ interface ExportedFile {
68
78
  }
69
79
  /** The `filename` of a `Content-Disposition` value (the `filename*` UTF-8 form first). */
70
80
  declare function dispositionFilename(value: string | null): string | null;
81
+ interface MultipartArgs<K extends OperationId> {
82
+ params?: RouteParams<K>;
83
+ file: Blob;
84
+ filename?: string;
85
+ /** For routes whose multipart form carries a second JSON field (e.g. `imports.create`). */
86
+ json?: unknown;
87
+ }
71
88
 
72
89
  /**
73
90
  * Namespaced, hand-written wrappers over `execute`/`executeMultipart`. Every
@@ -97,6 +114,8 @@ declare function createNamespaces(config: CoreConfig): {
97
114
  default_locale: string;
98
115
  locales: string[];
99
116
  tracking_enabled: boolean;
117
+ allowed_asset_hosts: string[];
118
+ merge_defaults: Record<string, string | number | boolean>;
100
119
  default_timezone: string | null;
101
120
  };
102
121
  company_id: string | null;
@@ -113,6 +132,8 @@ declare function createNamespaces(config: CoreConfig): {
113
132
  default_locale: string;
114
133
  locales: string[];
115
134
  tracking_enabled: boolean;
135
+ allowed_asset_hosts: string[];
136
+ merge_defaults: Record<string, string | number | boolean>;
116
137
  default_timezone: string | null;
117
138
  };
118
139
  company_id: string | null;
@@ -133,6 +154,8 @@ declare function createNamespaces(config: CoreConfig): {
133
154
  default_locale: string;
134
155
  locales: string[];
135
156
  tracking_enabled: boolean;
157
+ allowed_asset_hosts: string[];
158
+ merge_defaults: Record<string, string | number | boolean>;
136
159
  default_timezone: string | null;
137
160
  };
138
161
  company_id: string | null;
@@ -148,6 +171,8 @@ declare function createNamespaces(config: CoreConfig): {
148
171
  default_locale: string;
149
172
  locales: string[];
150
173
  tracking_enabled: boolean;
174
+ allowed_asset_hosts: string[];
175
+ merge_defaults: Record<string, string | number | boolean>;
151
176
  default_timezone: string | null;
152
177
  };
153
178
  company_id: string | null;
@@ -168,6 +193,8 @@ declare function createNamespaces(config: CoreConfig): {
168
193
  default_locale: string;
169
194
  locales: string[];
170
195
  tracking_enabled: boolean;
196
+ allowed_asset_hosts: string[];
197
+ merge_defaults: Record<string, string | number | boolean>;
171
198
  default_timezone: string | null;
172
199
  };
173
200
  company_id: string | null;
@@ -276,6 +303,8 @@ declare function createNamespaces(config: CoreConfig): {
276
303
  default_locale: string;
277
304
  locales: string[];
278
305
  tracking_enabled: boolean;
306
+ allowed_asset_hosts: string[];
307
+ merge_defaults: Record<string, string | number | boolean>;
279
308
  default_timezone: string | null;
280
309
  };
281
310
  company_id: string | null;
@@ -333,6 +362,7 @@ declare function createNamespaces(config: CoreConfig): {
333
362
  } | {
334
363
  type: "api_key";
335
364
  api_key_id: string;
365
+ on_behalf_of?: string | undefined;
336
366
  } | {
337
367
  type: "system";
338
368
  reason: string;
@@ -609,7 +639,9 @@ declare function createNamespaces(config: CoreConfig): {
609
639
  /**
610
640
  * Copies a remote image into the workspace's assets and answers with the
611
641
  * new asset, whose `url` is the service's own. The workspace setting
612
- * `asset_policy: 'service_only'` accepts only such addresses in a mail.
642
+ * `asset_policy: 'service_only'` accepts only such addresses in a mail,
643
+ * plus any host in `settings.allowed_asset_hosts` (the workspace's own
644
+ * website, typically), whose images need no copy.
613
645
  */
614
646
  import: (body: RouteBody<"assets.import">, opts?: RequestOpts) => Promise<{
615
647
  id: string;
@@ -2077,7 +2109,7 @@ declare function createNamespaces(config: CoreConfig): {
2077
2109
  created_at: string;
2078
2110
  updated_at: string;
2079
2111
  url: string;
2080
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2112
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2081
2113
  enabled: boolean;
2082
2114
  }[];
2083
2115
  next_cursor: string | null;
@@ -2089,7 +2121,7 @@ declare function createNamespaces(config: CoreConfig): {
2089
2121
  created_at: string;
2090
2122
  updated_at: string;
2091
2123
  url: string;
2092
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2124
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2093
2125
  enabled: boolean;
2094
2126
  };
2095
2127
  secret: string;
@@ -2100,7 +2132,7 @@ declare function createNamespaces(config: CoreConfig): {
2100
2132
  created_at: string;
2101
2133
  updated_at: string;
2102
2134
  url: string;
2103
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2135
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2104
2136
  enabled: boolean;
2105
2137
  }>;
2106
2138
  update: (id: string, body: RouteBody<"webhooks.update">, opts?: RequestOpts) => Promise<{
@@ -2109,7 +2141,7 @@ declare function createNamespaces(config: CoreConfig): {
2109
2141
  created_at: string;
2110
2142
  updated_at: string;
2111
2143
  url: string;
2112
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2144
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2113
2145
  enabled: boolean;
2114
2146
  }>;
2115
2147
  delete: (id: string, opts?: RequestOpts) => Promise<{
@@ -2122,7 +2154,7 @@ declare function createNamespaces(config: CoreConfig): {
2122
2154
  created_at: string;
2123
2155
  updated_at: string;
2124
2156
  url: string;
2125
- events: ("contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2157
+ events: ("template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook")[];
2126
2158
  enabled: boolean;
2127
2159
  };
2128
2160
  secret: string;
@@ -2136,7 +2168,7 @@ declare function createNamespaces(config: CoreConfig): {
2136
2168
  last_error: string | null;
2137
2169
  endpoint_id: string;
2138
2170
  event_id: string;
2139
- event_type: "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2171
+ event_type: "template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2140
2172
  last_status_code: number | null;
2141
2173
  next_attempt_at: string | null;
2142
2174
  delivered_at: string | null;
@@ -2151,7 +2183,7 @@ declare function createNamespaces(config: CoreConfig): {
2151
2183
  last_error: string | null;
2152
2184
  endpoint_id: string;
2153
2185
  event_id: string;
2154
- event_type: "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2186
+ event_type: "template.created" | "template.updated" | "template.deleted" | "contact.unsubscribed" | "contact.subscribed" | "import.finished" | "mailing.scheduled" | "mailing.schedule_failed" | "mailing.ab_winner_selected" | "message.sent" | "message.failed" | "contact.resubscribed" | "contact.bounced" | "mailing.finished" | "mailing.started" | "contact.tagged" | "contact.updated" | "automation.run_started" | "automation.run_completed" | "automation.run_exited" | "automation.run_failed" | "automation.webhook";
2155
2187
  last_status_code: number | null;
2156
2188
  next_attempt_at: string | null;
2157
2189
  delivered_at: string | null;
@@ -4378,9 +4410,11 @@ interface MailClientOptions extends BaseClientOptions {
4378
4410
  /** A workspace API key (`Authorization: Bearer <key>`), scoped to one workspace and to `full`, `send` or `read`. */
4379
4411
  apiKey: string;
4380
4412
  }
4381
- /** Every namespaced method, plus the two escape hatches: `request` for any operation id, `paginate` for cursor lists. */
4413
+ /** Every namespaced method, plus the escape hatches: `request` for any JSON operation id, `upload` for a multipart one, `paginate` for cursor lists. */
4382
4414
  interface MailClient extends MailNamespaces {
4383
4415
  request<K extends OperationId>(operationId: K, args?: ExecuteArgs<K>, opts?: RequestOpts): Promise<RouteResponse<K>>;
4416
+ /** The multipart routes (`assets.upload`, `imports.create`) by operation id, for a caller that dispatches generically. */
4417
+ upload<K extends OperationId>(operationId: K, args: MultipartArgs<K>, opts?: RequestOpts): Promise<RouteResponse<K>>;
4384
4418
  paginate<K extends PaginatableOperationId>(operationId: K, args?: PaginateArgs<K>, opts?: RequestOpts): AsyncGenerator<PageItem<K>, void, void>;
4385
4419
  /**
4386
4420
  * Checks the service's liveness probe (`HEALTH_PATH`, outside `/v1`, no
@@ -4477,4 +4511,4 @@ declare class MailResponseValidationError extends Error {
4477
4511
  /** A fresh idempotency key, reused across every retry of the same call. */
4478
4512
  declare function generateIdempotencyKey(): string;
4479
4513
 
4480
- export { type BaseClientOptions, type DashboardMailClient, type DashboardMailClientOptions, type DashboardUserContext, type ExecuteArgs, type ExportedFile, MailApiError, type MailClient, type MailClientOptions, MailNetworkError, MailResponseValidationError, MailTimeoutError, type PageItem, type PaginatableOperationId, type PaginateArgs, type RequestOpts, type ResponseMeta, createDashboardMailClient, createMailClient, dispositionFilename, generateIdempotencyKey };
4514
+ export { type BaseClientOptions, type DashboardMailClient, type DashboardMailClientOptions, type DashboardUserContext, type ExecuteArgs, type ExportedFile, MailApiError, type MailClient, type MailClientOptions, MailNetworkError, MailResponseValidationError, MailTimeoutError, type MultipartArgs, type PageItem, type PaginatableOperationId, type PaginateArgs, type RequestOpts, type ResponseMeta, createDashboardMailClient, createMailClient, dispositionFilename, generateIdempotencyKey };
package/dist/index.js CHANGED
@@ -129,6 +129,15 @@ function parseRetryAfterMs(header, now = Date.now) {
129
129
  }
130
130
 
131
131
  // src/core.ts
132
+ function onBehalfOfHeader(opts) {
133
+ if (opts.onBehalfOf === void 0) return {};
134
+ const label = opts.onBehalfOf.trim();
135
+ if (label.length === 0) return {};
136
+ if (label.length > import_mail_contract.ON_BEHALF_OF_MAX_LENGTH) {
137
+ throw new RangeError(`onBehalfOf is ${label.length} characters; the service accepts at most ${import_mail_contract.ON_BEHALF_OF_MAX_LENGTH}`);
138
+ }
139
+ return { [import_mail_contract.ON_BEHALF_OF_HEADER]: label };
140
+ }
132
141
  function responseMeta(response, requestId) {
133
142
  return {
134
143
  status: response.status,
@@ -178,6 +187,7 @@ async function send(config, operationId, args, opts, accept) {
178
187
  const hasJsonBody = route.body !== void 0;
179
188
  const bodyText = hasJsonBody ? JSON.stringify(args.body ?? {}) : void 0;
180
189
  const idempotencyKey = (0, import_mail_contract.acceptsIdempotencyKey)(route) ? opts.idempotencyKey ?? generateIdempotencyKey() : void 0;
190
+ const onBehalfOf = onBehalfOfHeader(opts);
181
191
  let lastError;
182
192
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
183
193
  const timeoutController = new AbortController();
@@ -187,6 +197,7 @@ async function send(config, operationId, args, opts, accept) {
187
197
  try {
188
198
  const headers = {
189
199
  ...config.authHeaders(),
200
+ ...onBehalfOf,
190
201
  accept
191
202
  };
192
203
  if (hasJsonBody) headers["content-type"] = "application/json";
@@ -296,6 +307,7 @@ async function executeMultipart(config, operationId, args, opts = {}) {
296
307
  const path = (0, import_mail_contract.buildPath)(route.path, args.params ?? {});
297
308
  const url = `${config.baseUrl.replace(/\/+$/, "")}${path}`;
298
309
  const idempotencyKey = (0, import_mail_contract.acceptsIdempotencyKey)(route) ? opts.idempotencyKey ?? generateIdempotencyKey() : void 0;
310
+ const onBehalfOf = onBehalfOfHeader(opts);
299
311
  let lastError;
300
312
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
301
313
  const timeoutController = new AbortController();
@@ -308,7 +320,7 @@ async function executeMultipart(config, operationId, args, opts = {}) {
308
320
  if (route.multipart.jsonField) {
309
321
  form.set(route.multipart.jsonField, JSON.stringify(args.json ?? {}));
310
322
  }
311
- const headers = { ...config.authHeaders(), accept: "application/json" };
323
+ const headers = { ...config.authHeaders(), ...onBehalfOf, accept: "application/json" };
312
324
  if (idempotencyKey) headers[import_mail_contract.IDEMPOTENCY_KEY_HEADER] = idempotencyKey;
313
325
  if (config.userAgent) headers["user-agent"] = config.userAgent;
314
326
  let response;
@@ -470,7 +482,9 @@ function createNamespaces(config) {
470
482
  /**
471
483
  * Copies a remote image into the workspace's assets and answers with the
472
484
  * new asset, whose `url` is the service's own. The workspace setting
473
- * `asset_policy: 'service_only'` accepts only such addresses in a mail.
485
+ * `asset_policy: 'service_only'` accepts only such addresses in a mail,
486
+ * plus any host in `settings.allowed_asset_hosts` (the workspace's own
487
+ * website, typically), whose images need no copy.
474
488
  */
475
489
  import: (body, opts) => execute(config, "assets.import", { body }, opts),
476
490
  get: (id, opts) => execute(config, "assets.get", { params: { id } }, opts)
@@ -698,6 +712,7 @@ function buildClient(config) {
698
712
  return {
699
713
  ...createNamespaces(config),
700
714
  request: (operationId, args, opts) => execute(config, operationId, args ?? {}, opts),
715
+ upload: (operationId, args, opts) => executeMultipart(config, operationId, args, opts),
701
716
  paginate: (operationId, args, opts) => paginate(config, operationId, args ?? {}, opts),
702
717
  health: (opts) => checkHealth(config, opts)
703
718
  };
package/dist/index.mjs CHANGED
@@ -7,6 +7,8 @@ import {
7
7
  BEARER_PREFIX,
8
8
  ErrorBody,
9
9
  IDEMPOTENCY_KEY_HEADER,
10
+ ON_BEHALF_OF_HEADER,
11
+ ON_BEHALF_OF_MAX_LENGTH,
10
12
  REQUEST_ID_HEADER,
11
13
  RETRY_AFTER_HEADER,
12
14
  USAGE_WARNING_HEADER,
@@ -111,6 +113,15 @@ function parseRetryAfterMs(header, now = Date.now) {
111
113
  }
112
114
 
113
115
  // src/core.ts
116
+ function onBehalfOfHeader(opts) {
117
+ if (opts.onBehalfOf === void 0) return {};
118
+ const label = opts.onBehalfOf.trim();
119
+ if (label.length === 0) return {};
120
+ if (label.length > ON_BEHALF_OF_MAX_LENGTH) {
121
+ throw new RangeError(`onBehalfOf is ${label.length} characters; the service accepts at most ${ON_BEHALF_OF_MAX_LENGTH}`);
122
+ }
123
+ return { [ON_BEHALF_OF_HEADER]: label };
124
+ }
114
125
  function responseMeta(response, requestId) {
115
126
  return {
116
127
  status: response.status,
@@ -160,6 +171,7 @@ async function send(config, operationId, args, opts, accept) {
160
171
  const hasJsonBody = route.body !== void 0;
161
172
  const bodyText = hasJsonBody ? JSON.stringify(args.body ?? {}) : void 0;
162
173
  const idempotencyKey = acceptsIdempotencyKey(route) ? opts.idempotencyKey ?? generateIdempotencyKey() : void 0;
174
+ const onBehalfOf = onBehalfOfHeader(opts);
163
175
  let lastError;
164
176
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
165
177
  const timeoutController = new AbortController();
@@ -169,6 +181,7 @@ async function send(config, operationId, args, opts, accept) {
169
181
  try {
170
182
  const headers = {
171
183
  ...config.authHeaders(),
184
+ ...onBehalfOf,
172
185
  accept
173
186
  };
174
187
  if (hasJsonBody) headers["content-type"] = "application/json";
@@ -278,6 +291,7 @@ async function executeMultipart(config, operationId, args, opts = {}) {
278
291
  const path = buildPath(route.path, args.params ?? {});
279
292
  const url = `${config.baseUrl.replace(/\/+$/, "")}${path}`;
280
293
  const idempotencyKey = acceptsIdempotencyKey(route) ? opts.idempotencyKey ?? generateIdempotencyKey() : void 0;
294
+ const onBehalfOf = onBehalfOfHeader(opts);
281
295
  let lastError;
282
296
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
283
297
  const timeoutController = new AbortController();
@@ -290,7 +304,7 @@ async function executeMultipart(config, operationId, args, opts = {}) {
290
304
  if (route.multipart.jsonField) {
291
305
  form.set(route.multipart.jsonField, JSON.stringify(args.json ?? {}));
292
306
  }
293
- const headers = { ...config.authHeaders(), accept: "application/json" };
307
+ const headers = { ...config.authHeaders(), ...onBehalfOf, accept: "application/json" };
294
308
  if (idempotencyKey) headers[IDEMPOTENCY_KEY_HEADER] = idempotencyKey;
295
309
  if (config.userAgent) headers["user-agent"] = config.userAgent;
296
310
  let response;
@@ -452,7 +466,9 @@ function createNamespaces(config) {
452
466
  /**
453
467
  * Copies a remote image into the workspace's assets and answers with the
454
468
  * new asset, whose `url` is the service's own. The workspace setting
455
- * `asset_policy: 'service_only'` accepts only such addresses in a mail.
469
+ * `asset_policy: 'service_only'` accepts only such addresses in a mail,
470
+ * plus any host in `settings.allowed_asset_hosts` (the workspace's own
471
+ * website, typically), whose images need no copy.
456
472
  */
457
473
  import: (body, opts) => execute(config, "assets.import", { body }, opts),
458
474
  get: (id, opts) => execute(config, "assets.get", { params: { id } }, opts)
@@ -680,6 +696,7 @@ function buildClient(config) {
680
696
  return {
681
697
  ...createNamespaces(config),
682
698
  request: (operationId, args, opts) => execute(config, operationId, args ?? {}, opts),
699
+ upload: (operationId, args, opts) => executeMultipart(config, operationId, args, opts),
683
700
  paginate: (operationId, args, opts) => paginate(config, operationId, args ?? {}, opts),
684
701
  health: (opts) => checkHealth(config, opts)
685
702
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.2.0",
6
+ "version": "0.3.0",
7
7
  "description": "Typed client for the Lumitra Mail v1 API: Node and edge runtimes, retries with idempotency, cursor pagination, webhook verification",
8
8
  "license": "MIT",
9
9
  "repository": {
@@ -32,7 +32,7 @@
32
32
  "LICENSE"
33
33
  ],
34
34
  "dependencies": {
35
- "@marlinjai/mail-contract": "^0.2.0"
35
+ "@marlinjai/mail-contract": "^0.3.0"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "zod": "^3.25.0"