shipmail-cli 0.5.4 → 0.6.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.
Files changed (3) hide show
  1. package/README.md +6 -12
  2. package/dist/cli.js +23 -119
  3. package/package.json +2 -2
package/README.md CHANGED
@@ -14,7 +14,7 @@ Most commands require an API key. Create one in the Shipmail dashboard and expor
14
14
  export SHIPMAIL_API_KEY="sm_live_..."
15
15
  ```
16
16
 
17
- You can also pass `--api-key` to any command. Use `SHIPMAIL_BASE_URL` or `--base-url` when targeting a non-production API. Approved partners can set `SHIPMAIL_ORGANIZATION_ID` or pass `--organization-id` for delegated infrastructure calls.
17
+ You can also pass `--api-key` to any command. Use `SHIPMAIL_BASE_URL` or `--base-url` when targeting a non-production API.
18
18
 
19
19
  ## Common Commands
20
20
 
@@ -125,14 +125,6 @@ shipmail webhooks create \
125
125
  --events message.received,message.bounced
126
126
  shipmail webhooks deliveries whk_123 --status failed
127
127
  shipmail webhooks replay-delivery whk_123 dlv_123 --idempotency-key replay-123
128
-
129
- # Partner beta lifecycle and delegated infrastructure
130
- shipmail partner organizations create --name "Operator" --external-reference operator_123 --owner-email owner@example.com --mailbox-limit 3 --data-classification internal_test
131
- shipmail partner usage
132
- shipmail partner credential-grants list
133
- shipmail partner credential-grants consume grant_123 --name "Embedded webmail"
134
- shipmail domains list --organization-id 00000000-0000-4000-8000-000000000123
135
- shipmail mailboxes create --organization-id 00000000-0000-4000-8000-000000000123 --domain-id dom_123 --address support --generate-password
136
128
  ```
137
129
 
138
130
  Paragraph, quote, callout, list-item, and column bodies in `--blocks` accept bare text or
@@ -160,6 +152,7 @@ Use repeatable `--header "Name: value"` flags for request headers. Use `--output
160
152
  - `api <METHOD> <PATH>`
161
153
  - `domains list|search|create|get|verify|delete`
162
154
  - `mailboxes list|create|get|suspend|resume|forwarding|forwarding-add|forwarding-remove|app-passwords|folders|identities|stage-attachment|prepare-attachment-upload`
155
+ - `members list|get`
163
156
  - `inbox list|message|threads|thread|thread-state|draft|send-draft|reply-message|reply-thread|update|move`
164
157
  - `reply-scans create|status|results`
165
158
  - `messages send|list|analytics|get|reply` (test keys also support `--sandbox-outcome`)
@@ -174,9 +167,10 @@ Use repeatable `--header "Name: value"` flags for request headers. Use `--output
174
167
  - `newsletter-domains list`
175
168
  - `newsletters create|update|preview|preflight|test-send|schedule|cancel|resume`
176
169
  - `newsletter-assets list|upload|register-url`
177
- - `partner organizations list|create|get|update|invite|suspend|resume|offboard`
178
- - `partner credential-grants list|consume`
179
- - `partner usage`
170
+
171
+ Member output uses the roles `owner`, `admin`, and `member`. Its `mailbox_access.scope` is `all` or
172
+ `selected`; `mailbox_ids` is empty for `all`, while selected IDs may be limited to mailboxes the
173
+ API key can reach.
180
174
 
181
175
  Configure a publisher-owned Atom self URL and the number of recent issues:
182
176
 
package/dist/cli.js CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  } from "shipmail";
16
16
 
17
17
  // src/version.ts
18
- var VERSION = "0.5.4";
18
+ var VERSION = "0.6.1";
19
19
 
20
20
  // src/cli.ts
21
21
  var DEFAULT_BASE_URL = "https://shipmail.to/api/v1";
@@ -166,9 +166,6 @@ function baseUrl(parsed, env) {
166
166
  if (!raw) return DEFAULT_BASE_URL;
167
167
  return validateBaseUrl(raw, env["SHIPMAIL_ALLOW_INSECURE_BASE_URL"] === "1");
168
168
  }
169
- function organizationId(parsed, env) {
170
- return getString(parsed.options, "organization-id") ?? env["SHIPMAIL_ORGANIZATION_ID"];
171
- }
172
169
  function requireApiKey(parsed, env) {
173
170
  const key = apiKey(parsed, env);
174
171
  if (!key) {
@@ -181,7 +178,6 @@ function createClient(parsed, options) {
181
178
  const config = {
182
179
  apiKey: requireApiKey(parsed, env),
183
180
  baseUrl: baseUrl(parsed, env),
184
- organizationId: organizationId(parsed, env),
185
181
  ...options.fetch ? { fetch: options.fetch } : {}
186
182
  };
187
183
  return new ShipmailClient(config);
@@ -281,6 +277,7 @@ async function newsletterCreateParams(options) {
281
277
  const archive_visibility = parseArchiveVisibility(options);
282
278
  const feed_entry_url = getString(options, "feed-entry-url");
283
279
  const styling_mode = parseStylingMode(options);
280
+ const track_engagement = getBoolean(options, "track-engagement");
284
281
  const preview_text = getString(options, "preview-text");
285
282
  return {
286
283
  audience_id,
@@ -294,7 +291,8 @@ async function newsletterCreateParams(options) {
294
291
  ...send_window_hours !== void 0 ? { send_window_hours } : {},
295
292
  ...archive_visibility !== void 0 ? { archive_visibility } : {},
296
293
  ...feed_entry_url !== void 0 ? { feed_entry_url } : {},
297
- ...styling_mode !== void 0 ? { styling_mode } : {}
294
+ ...styling_mode !== void 0 ? { styling_mode } : {},
295
+ ...track_engagement !== void 0 ? { track_engagement } : {}
298
296
  };
299
297
  }
300
298
  async function newsletterUpdateParams(options) {
@@ -307,6 +305,7 @@ async function newsletterUpdateParams(options) {
307
305
  const archive_visibility = parseArchiveVisibility(options);
308
306
  const feed_entry_url = getString(options, "feed-entry-url");
309
307
  const styling_mode = parseStylingMode(options);
308
+ const track_engagement = getBoolean(options, "track-engagement");
310
309
  const blocksInput = getString(options, "blocks");
311
310
  const bodyHtmlInput = getString(options, "body-html");
312
311
  const bodyTextInput = getString(options, "body-text");
@@ -325,7 +324,8 @@ async function newsletterUpdateParams(options) {
325
324
  ...send_window_hours !== void 0 ? { send_window_hours } : {},
326
325
  ...archive_visibility !== void 0 ? { archive_visibility } : {},
327
326
  ...feed_entry_url !== void 0 ? { feed_entry_url } : {},
328
- ...styling_mode !== void 0 ? { styling_mode } : {}
327
+ ...styling_mode !== void 0 ? { styling_mode } : {},
328
+ ...track_engagement !== void 0 ? { track_engagement } : {}
329
329
  };
330
330
  if (Object.keys(params).length === 0) {
331
331
  throw new CliUsageError("Provide at least one field to update.");
@@ -358,10 +358,6 @@ async function rawApiRequest(parsed, runOptions, method, path, body, authRequire
358
358
  const key = apiKey(parsed, env);
359
359
  if (key) headers["Authorization"] = `Bearer ${key}`;
360
360
  }
361
- const targetOrganizationId = organizationId(parsed, env);
362
- if (targetOrganizationId) {
363
- headers["X-Shipmail-Organization-Id"] = targetOrganizationId;
364
- }
365
361
  let requestBody;
366
362
  if (body !== void 0) {
367
363
  headers["Content-Type"] = "application/json";
@@ -479,8 +475,8 @@ Usage:
479
475
  --name "July changelog" \\
480
476
  --subject "What shipped in July" \\
481
477
  --blocks @blocks.json \\
482
- [--feed-entry-url https://example.com/post] [--styling-mode styled|plain]
483
- shipmail newsletters update nws_789 --subject "Updated subject" --blocks @blocks-v2.json [--feed-entry-url https://example.com/post] [--styling-mode styled|plain]
478
+ [--feed-entry-url https://example.com/post] [--styling-mode styled|plain] [--track-engagement true|false]
479
+ shipmail newsletters update nws_789 --subject "Updated subject" --blocks @blocks-v2.json [--feed-entry-url https://example.com/post] [--styling-mode styled|plain] [--track-engagement true|false]
484
480
  shipmail newsletters preview <id>
485
481
  shipmail newsletters preflight <id>
486
482
  shipmail newsletters test-send <id> --recipient-email owner@example.com
@@ -510,9 +506,9 @@ Usage:
510
506
  shipmail audiences subscribers resubscribe <audience-id> <subscriber-id> --consent-source "Signup form"
511
507
  shipmail audiences subscribers remove <audience-id> <subscriber-id>
512
508
  shipmail calendar events list --mailbox hello@example.com --from 2026-08-01T00:00:00Z --to 2026-08-08T00:00:00Z [--expand true] [--limit 100]
513
- shipmail calendar events create --mailbox hello@example.com --title "Sync" --start 2026-08-01T14:00:00 [--timezone Europe/Paris] [--duration PT30M] [--invitation-language en|fr|es] [--attendees JSON|@file] [--reminders JSON|@file]
509
+ shipmail calendar events create --mailbox hello@example.com --title "Sync" --start 2026-08-01T14:00:00 [--timezone Europe/Paris] [--duration PT30M] [--invitation-language en|fr|es] [--attendees JSON|@file] [--reminders JSON|@file] [--operation-key key] [--send-invitations true|false]
514
510
  shipmail calendar events get <event-id> --mailbox hello@example.com
515
- shipmail calendar events update <event-id> --mailbox hello@example.com [--title "..."] [--start ...] [--invitation-language en|fr|es]
511
+ shipmail calendar events update <event-id> --mailbox hello@example.com [--title "..."] [--start ...] [--invitation-language en|fr|es] [--operation-key key] [--expected-revision sha256] [--send-guest-updates true|false]
516
512
  shipmail calendar events delete <event-id> --mailbox hello@example.com
517
513
  shipmail calendar availability --mailbox hello@example.com --from 2026-08-03T00:00:00Z --to 2026-08-04T00:00:00Z [--duration 30] [--days 1,2,3,4,5] [--window-start 540] [--window-end 1020]
518
514
  shipmail booking-pages list [--limit 25] [--cursor cur]
@@ -520,17 +516,6 @@ Usage:
520
516
  shipmail booking-pages get <id>
521
517
  shipmail booking-pages update <id> [--name "..."] [--conferencing-provider zoom|google_meet|none] [--active false]
522
518
  shipmail booking-pages delete <id>
523
- shipmail partner organizations list
524
- shipmail partner organizations create --name "Operator" --external-reference op_123 --owner-email owner@example.com [--mailbox-limit 3] [--data-classification internal_test|customer]
525
- shipmail partner organizations get <id>
526
- shipmail partner organizations update <id> [--name "Operator"] [--mailbox-limit 5]
527
- shipmail partner organizations invite <id> [--owner-email owner@example.com]
528
- shipmail partner organizations suspend <id>
529
- shipmail partner organizations resume <id>
530
- shipmail partner organizations offboard <id>
531
- shipmail partner credential-grants list
532
- shipmail partner credential-grants consume <grant-id> [--name "Marketstead webmail"] [--expires-at 2026-10-01T00:00:00Z] [--allowed-cidr 203.0.113.0/24]
533
- shipmail partner usage
534
519
 
535
520
  Booking page conferencing:
536
521
  --conferencing-provider <zoom|google_meet> Create a meeting for every booking.
@@ -540,9 +525,16 @@ Conversation IDs:
540
525
  <thread-id> accepts a conversation ID (thd_...) or the mail-server thread ID. Store the
541
526
  conversation_id every response carries. thread_id is deprecated and unchanged.
542
527
 
528
+ Member access output:
529
+ role is owner, admin, or member. mailbox_access.scope is all or selected. mailbox_ids is empty
530
+ for all; selected IDs may be limited to mailboxes the API key can reach.
531
+
543
532
  Newsletter styling:
544
533
  --styling-mode <styled|plain> styled applies Shipmail's email theme. plain sends your HTML without injected styles, width, or centering, so the reader's email client styles it.
545
534
 
535
+ Newsletter tracking:
536
+ --track-engagement <true|false> Track opens and clicks for this issue. Off by default. Changes only while the issue is a draft or scheduled for later.
537
+
546
538
  Newsletter block prose:
547
539
  Paragraph, quote, callout, list-item, and column bodies accept bare text or sanitized inline HTML. Use <p> and <br> for line breaks.
548
540
 
@@ -552,7 +544,6 @@ Newsletter feeds:
552
544
  Global options:
553
545
  --api-key <key> API key. Defaults to SHIPMAIL_API_KEY.
554
546
  --base-url <url> API base URL. Defaults to SHIPMAIL_BASE_URL or ${DEFAULT_BASE_URL}.
555
- --organization-id Delegated child organization for supported infrastructure commands.
556
547
  --header "K: V" Extra header for the generic api command. Repeatable.
557
548
 
558
549
  Environment:
@@ -560,7 +551,6 @@ Environment:
560
551
  SHIPMAIL_BASE_URL Optional API base URL. Must be https on shipmail.to.
561
552
  SHIPMAIL_ALLOW_INSECURE_BASE_URL=1
562
553
  Permit a non-https or non-shipmail.to base URL (development only).
563
- SHIPMAIL_ORGANIZATION_ID Optional delegated child organization ID.
564
554
  `;
565
555
  }
566
556
  function requirePositional(positional, index, label) {
@@ -2024,6 +2014,8 @@ async function runCalendarEvents(client, parsed, out) {
2024
2014
  title: getRequiredString(options, "title"),
2025
2015
  start: getRequiredString(options, "start"),
2026
2016
  calendar_id: getString(options, "calendar-id"),
2017
+ operation_key: getString(options, "operation-key"),
2018
+ send_invitations: getBoolean(options, "send-invitations"),
2027
2019
  ...await calendarEventFields(options)
2028
2020
  };
2029
2021
  writeJson(out, await client.calendar.events.create(params));
@@ -2043,6 +2035,9 @@ async function runCalendarEvents(client, parsed, out) {
2043
2035
  mailbox: getRequiredString(options, "mailbox"),
2044
2036
  title: getString(options, "title"),
2045
2037
  start: getString(options, "start"),
2038
+ operation_key: getString(options, "operation-key"),
2039
+ expected_revision: getString(options, "expected-revision"),
2040
+ send_guest_updates: getBoolean(options, "send-guest-updates"),
2046
2041
  ...await calendarEventFields(options)
2047
2042
  };
2048
2043
  writeJson(out, await client.calendar.events.update(id, params));
@@ -2200,96 +2195,6 @@ async function runAutomations(client, parsed, out) {
2200
2195
  }
2201
2196
  throw new CliUsageError("Unknown automations command.");
2202
2197
  }
2203
- async function runPartner(client, parsed, out) {
2204
- const group = parsed.positional[1];
2205
- if (group === "usage") {
2206
- writeJson(out, await client.partner.usage());
2207
- return;
2208
- }
2209
- if (group === "credential-grants") {
2210
- const command2 = requirePositional(parsed.positional, 2, "credential grant command");
2211
- if (command2 === "list") {
2212
- writeJson(out, await client.partner.listMailboxCredentialGrants());
2213
- return;
2214
- }
2215
- if (command2 !== "consume")
2216
- throw new CliUsageError("Unknown partner credential-grants command.");
2217
- const grantId = requirePositional(parsed.positional, 3, "credential grant id");
2218
- const name = getString(parsed.options, "name");
2219
- const expiresAt = getString(parsed.options, "expires-at");
2220
- const allowedCidrs = getStringList(parsed.options, "allowed-cidr");
2221
- writeJson(
2222
- out,
2223
- await client.partner.consumeMailboxCredentialGrant(grantId, {
2224
- ...name ? { name } : {},
2225
- ...expiresAt ? { expires_at: expiresAt } : {},
2226
- ...allowedCidrs.length > 0 ? { allowed_cidrs: allowedCidrs } : {}
2227
- })
2228
- );
2229
- return;
2230
- }
2231
- if (group !== "organizations") throw new CliUsageError("Unknown partner command.");
2232
- const command = parsed.positional[2];
2233
- if (command === "list") {
2234
- writeJson(out, await client.partner.listOrganizations());
2235
- return;
2236
- }
2237
- if (command === "create") {
2238
- const classification = getString(parsed.options, "data-classification") ?? "customer";
2239
- if (classification !== "internal_test" && classification !== "customer") {
2240
- throw new CliUsageError("--data-classification must be internal_test or customer.");
2241
- }
2242
- const params = {
2243
- name: getRequiredString(parsed.options, "name"),
2244
- external_reference: getRequiredString(parsed.options, "external-reference"),
2245
- owner_email: getRequiredString(parsed.options, "owner-email"),
2246
- mailbox_limit: getNumber(parsed.options, "mailbox-limit") ?? 3,
2247
- data_classification: classification
2248
- };
2249
- writeJson(out, await client.partner.createOrganization(params));
2250
- return;
2251
- }
2252
- const id = requirePositional(parsed.positional, 3, "partner organization id");
2253
- if (command === "get") {
2254
- writeJson(out, await client.partner.getOrganization(id));
2255
- return;
2256
- }
2257
- if (command === "update") {
2258
- const name = getString(parsed.options, "name");
2259
- const mailboxLimit = getNumber(parsed.options, "mailbox-limit");
2260
- if (name === void 0 && mailboxLimit === void 0) {
2261
- throw new CliUsageError("Provide --name or --mailbox-limit.");
2262
- }
2263
- const params = {
2264
- ...name !== void 0 ? { name } : {},
2265
- ...mailboxLimit !== void 0 ? { mailbox_limit: mailboxLimit } : {}
2266
- };
2267
- writeJson(out, await client.partner.updateOrganization(id, params));
2268
- return;
2269
- }
2270
- if (command === "invite") {
2271
- writeJson(
2272
- out,
2273
- await client.partner.resendOwnershipInvitation(id, {
2274
- owner_email: getString(parsed.options, "owner-email")
2275
- })
2276
- );
2277
- return;
2278
- }
2279
- if (command === "suspend") {
2280
- writeJson(out, await client.partner.suspendOrganization(id));
2281
- return;
2282
- }
2283
- if (command === "resume") {
2284
- writeJson(out, await client.partner.resumeOrganization(id));
2285
- return;
2286
- }
2287
- if (command === "offboard") {
2288
- writeJson(out, await client.partner.offboardOrganization(id));
2289
- return;
2290
- }
2291
- throw new CliUsageError("Unknown partner organizations command.");
2292
- }
2293
2198
  function writeError(err, errOut) {
2294
2199
  if (err instanceof CliUsageError) {
2295
2200
  errOut.write(`Error: ${err.message}
@@ -2375,7 +2280,6 @@ async function runCli(argv, options = {}) {
2375
2280
  else if (command === "audiences") await runAudiences(client, parsed, out);
2376
2281
  else if (command === "calendar") await runCalendar(client, parsed, out);
2377
2282
  else if (command === "booking-pages") await runBookingPages(client, parsed, out);
2378
- else if (command === "partner") await runPartner(client, parsed, out);
2379
2283
  else throw new CliUsageError(`Unknown command: ${command}.`);
2380
2284
  return 0;
2381
2285
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shipmail-cli",
3
- "version": "0.5.4",
3
+ "version": "0.6.1",
4
4
  "description": "Official CLI for the Shipmail API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -41,7 +41,7 @@
41
41
  "access": "public"
42
42
  },
43
43
  "dependencies": {
44
- "shipmail": "0.5.10"
44
+ "shipmail": "0.6.2"
45
45
  },
46
46
  "devDependencies": {
47
47
  "tsup": "^8.4.0",