nixflex 0.3.0 → 0.4.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/CHANGELOG.md CHANGED
@@ -1,3 +1,12 @@
1
+ ## 0.4.0
2
+
3
+ - New: `client.storage` - connect your own S3-compatible bucket for call recordings (data residency). `storage.set()` verifies with a probe write before saving, `storage.get()` never returns the secret, `storage.delete()` disconnects. Recordings then upload to your bucket and `recording_url` becomes a `byo:` path. See https://docs.nixflex.com/advanced/your-own-storage
4
+
5
+ ## 0.3.1 (2026-08-24)
6
+
7
+ - Voicemail as a structured setting: `voicemail_leave_enabled` + `voicemail_message` on Agent (applies to dashboard-imported numbers) and on PhoneNumber / PhoneNumberUpdateParams (the only voicemail control for API-imported numbers - no inheritance across the two worlds)
8
+ - Enabling without a message is rejected with `voicemail_message_required`
9
+ - No breaking changes.
1
10
  ## 0.3.0 (2026-08-23)
2
11
 
3
12
  - Call type: `charged_minutes` (minutes actually billed - transfers stop the meter at handoff, so this can be less than the recording length)
package/dist/index.cjs CHANGED
@@ -465,6 +465,28 @@ var UsageResource = class {
465
465
  return this.http.request("GET", "/usage", void 0, void 0, opts);
466
466
  }
467
467
  };
468
+ var Storage = class {
469
+ constructor(http) {
470
+ this.http = http;
471
+ }
472
+ http;
473
+ /** Connect your own S3-compatible bucket for call recordings (data residency).
474
+ * The connection is verified with a probe write BEFORE saving - broken
475
+ * credentials are rejected, never stored. Recordings then upload to your
476
+ * bucket and Nixflex keeps no copy; recording_url becomes a byo: path. */
477
+ set(params, opts) {
478
+ return this.http.request("PUT", "/account/storage", params, void 0, opts);
479
+ }
480
+ /** Current storage configuration. The secret is never included. */
481
+ get(opts) {
482
+ return this.http.request("GET", "/account/storage", void 0, void 0, opts);
483
+ }
484
+ /** Disconnect and clear. Recordings return to Nixflex EU storage from the
485
+ * next call; files already in your bucket are untouched - they are yours. */
486
+ delete(opts) {
487
+ return this.http.request("DELETE", "/account/storage", void 0, void 0, opts);
488
+ }
489
+ };
468
490
  var Webhooks = class {
469
491
  constructor(http) {
470
492
  this.http = http;
@@ -512,6 +534,8 @@ var Nixflex = class {
512
534
  usage;
513
535
  /** Per-number post-call webhook configuration. */
514
536
  webhooks;
537
+ /** Your own S3-compatible recording storage (data residency). */
538
+ storage;
515
539
  constructor(options) {
516
540
  const http = new HttpClient(options);
517
541
  this.agents = new Agents(http);
@@ -522,6 +546,7 @@ var Nixflex = class {
522
546
  this.keys = new Keys(http);
523
547
  this.usage = new UsageResource(http);
524
548
  this.webhooks = new Webhooks(http);
549
+ this.storage = new Storage(http);
525
550
  }
526
551
  /** Create a brand-new API key (unauthenticated signup endpoint - most
527
552
  * developers use the dashboard instead). The key_secret is shown ONCE.
package/dist/index.d.cts CHANGED
@@ -66,6 +66,12 @@ interface AgentCreateParams {
66
66
  amd_enabled?: boolean;
67
67
  /** Keypad digits instead of speech. Three-state: true/false explicit, null = not set (a number's own setting decides). */
68
68
  dtmf_enabled?: boolean | null;
69
+ /** Leave a message on detected voicemails. Applies to DASHBOARD-imported numbers on
70
+ * this agent; API-imported numbers use their own per-number setting instead. Enabling
71
+ * without voicemail_message is rejected with voicemail_message_required. */
72
+ voicemail_leave_enabled?: boolean;
73
+ /** Spoken word for word on voicemail when enabled - the agent never rewrites it. */
74
+ voicemail_message?: string | null;
69
75
  /** Where to POST post-call data. */
70
76
  webhook_url?: string | null;
71
77
  /** Agent can end the call cleanly. Default true. */
@@ -124,6 +130,8 @@ interface Agent {
124
130
  fallback_message: string;
125
131
  post_call_sms_enabled?: boolean;
126
132
  post_call_sms_template?: string | null;
133
+ voicemail_leave_enabled?: boolean;
134
+ voicemail_message?: string | null;
127
135
  data_extraction_fields?: unknown[];
128
136
  is_active: boolean;
129
137
  created_at: string;
@@ -385,6 +393,12 @@ interface PhoneNumber {
385
393
  custom_prompt?: string | null;
386
394
  voice_id?: string | null;
387
395
  sms_reply_enabled?: boolean;
396
+ /** This number's own voicemail setting - the ONLY one that applies to API-imported
397
+ * numbers (dashboard-imported numbers follow the agent). null = not set = silent
398
+ * hangup on voicemail. */
399
+ voicemail_leave_enabled?: boolean | null;
400
+ /** Spoken word for word on a detected voicemail when enabled. */
401
+ voicemail_message?: string | null;
388
402
  sms_prompt?: string | null;
389
403
  web_prompt?: string | null;
390
404
  speaking_rate?: number | null;
@@ -401,6 +415,12 @@ interface PhoneNumberUpdateParams {
401
415
  voice_id?: string | null;
402
416
  /** SMS agent auto-reply on/off. Default false. */
403
417
  sms_reply_enabled?: boolean;
418
+ /** This number's own voicemail toggle - the only voicemail control for API-imported
419
+ * numbers. Enabling without a message (here or already saved) is rejected with
420
+ * voicemail_message_required. null clears. */
421
+ voicemail_leave_enabled?: boolean | null;
422
+ /** Spoken word for word on voicemail. Max 2000. null clears. */
423
+ voicemail_message?: string | null;
404
424
  /** SMS agent instructions (independent channel). Max 20000. null clears. */
405
425
  sms_prompt?: string | null;
406
426
  /** Web agent instructions (independent channel). Max 20000. null clears. */
@@ -556,6 +576,38 @@ interface WebhookConfigResponse {
556
576
  phone_number?: string;
557
577
  url?: string | null;
558
578
  }
579
+ /** Your own S3-compatible recording storage (BYO storage). */
580
+ interface StorageConfig {
581
+ storage_enabled: boolean;
582
+ endpoint: string | null;
583
+ region: string | null;
584
+ bucket: string | null;
585
+ access_key: string | null;
586
+ }
587
+ interface StorageSetParams {
588
+ /** The exact bucket name at your provider. */
589
+ bucket: string;
590
+ /** Access key ID with permission to write objects. */
591
+ access_key: string;
592
+ /** Secret access key. Write-only - stored encrypted, never returned. */
593
+ secret_key: string;
594
+ /** https:// endpoint of your provider. Leave empty for Amazon S3. */
595
+ endpoint?: string;
596
+ /** Your bucket's region. Defaults to auto. */
597
+ region?: string;
598
+ }
599
+ interface StorageSetResponse {
600
+ ok: boolean;
601
+ storage_enabled: boolean;
602
+ bucket: string;
603
+ endpoint: string | null;
604
+ region: string;
605
+ verified: boolean;
606
+ }
607
+ interface StorageDeleteResponse {
608
+ ok: boolean;
609
+ storage_enabled: boolean;
610
+ }
559
611
 
560
612
  declare class PhoneNumbers {
561
613
  private readonly http;
@@ -643,6 +695,21 @@ declare class UsageResource {
643
695
  get(opts?: RequestOptions): Promise<Usage>;
644
696
  }
645
697
 
698
+ declare class Storage {
699
+ private readonly http;
700
+ constructor(http: HttpClient);
701
+ /** Connect your own S3-compatible bucket for call recordings (data residency).
702
+ * The connection is verified with a probe write BEFORE saving - broken
703
+ * credentials are rejected, never stored. Recordings then upload to your
704
+ * bucket and Nixflex keeps no copy; recording_url becomes a byo: path. */
705
+ set(params: StorageSetParams, opts?: RequestOptions): Promise<StorageSetResponse>;
706
+ /** Current storage configuration. The secret is never included. */
707
+ get(opts?: RequestOptions): Promise<StorageConfig>;
708
+ /** Disconnect and clear. Recordings return to Nixflex EU storage from the
709
+ * next call; files already in your bucket are untouched - they are yours. */
710
+ delete(opts?: RequestOptions): Promise<StorageDeleteResponse>;
711
+ }
712
+
646
713
  declare class Webhooks {
647
714
  private readonly http;
648
715
  constructor(http: HttpClient);
@@ -732,6 +799,8 @@ declare class Nixflex {
732
799
  readonly usage: UsageResource;
733
800
  /** Per-number post-call webhook configuration. */
734
801
  readonly webhooks: Webhooks;
802
+ /** Your own S3-compatible recording storage (data residency). */
803
+ readonly storage: Storage;
735
804
  constructor(options: NixflexClientOptions);
736
805
  /** Create a brand-new API key (unauthenticated signup endpoint - most
737
806
  * developers use the dashboard instead). The key_secret is shown ONCE.
@@ -742,4 +811,4 @@ declare class Nixflex {
742
811
  }, baseUrl?: string): Promise<KeyCreateResponse>;
743
812
  }
744
813
 
745
- export { type Agent, type AgentCreateParams, type AgentDeleteResponse, type AgentUpdateParams, type BatchCampaignParams, type BatchCreateResponse, type BatchInvalidEntry, type BatchLaunchResponse, type BatchRecipient, type Call, type CallDeleteAllResponse, type CallDeleteResponse, type CallDirection, type CallerSentiment, type KeyCreateResponse, type KeyRotateResponse, type ListParams, type MonitorToggleResponse, Nixflex, type NixflexAPIErrorBody, NixflexAuthenticationError, type NixflexClientOptions, NixflexConnectionError, NixflexError, NixflexInvalidRequestError, NixflexNotFoundError, NixflexPaymentRequiredError, NixflexRateLimitError, NixflexServerError, type OutboundCallParams, type OutboundCallResponse, type PhoneNumber, type PhoneNumberDeleteResponse, type PhoneNumberImportParams, type PhoneNumberListResponse, type PhoneNumberUpdateParams, type RequestOptions, type ResponseLength, type SmsCampaign, type SmsCampaignCreateParams, type SmsCampaignDeleteResponse, type SmsCampaignLaunchResponse, type SmsCampaignListResponse, type SmsCampaignRecipient, type SmsCampaignStatus, type SmsSendParams, type SmsSendResponse, type TransferType, type Usage, type VerifyOptions, type WebCallsToggleResponse, type WebhookConfigResponse, type Weekday, Nixflex as default, errorFromResponse, verifyWebhookSignature };
814
+ export { type Agent, type AgentCreateParams, type AgentDeleteResponse, type AgentUpdateParams, type BatchCampaignParams, type BatchCreateResponse, type BatchInvalidEntry, type BatchLaunchResponse, type BatchRecipient, type Call, type CallDeleteAllResponse, type CallDeleteResponse, type CallDirection, type CallerSentiment, type KeyCreateResponse, type KeyRotateResponse, type ListParams, type MonitorToggleResponse, Nixflex, type NixflexAPIErrorBody, NixflexAuthenticationError, type NixflexClientOptions, NixflexConnectionError, NixflexError, NixflexInvalidRequestError, NixflexNotFoundError, NixflexPaymentRequiredError, NixflexRateLimitError, NixflexServerError, type OutboundCallParams, type OutboundCallResponse, type PhoneNumber, type PhoneNumberDeleteResponse, type PhoneNumberImportParams, type PhoneNumberListResponse, type PhoneNumberUpdateParams, type RequestOptions, type ResponseLength, type SmsCampaign, type SmsCampaignCreateParams, type SmsCampaignDeleteResponse, type SmsCampaignLaunchResponse, type SmsCampaignListResponse, type SmsCampaignRecipient, type SmsCampaignStatus, type SmsSendParams, type SmsSendResponse, type StorageConfig, type StorageDeleteResponse, type StorageSetParams, type StorageSetResponse, type TransferType, type Usage, type VerifyOptions, type WebCallsToggleResponse, type WebhookConfigResponse, type Weekday, Nixflex as default, errorFromResponse, verifyWebhookSignature };
package/dist/index.d.ts CHANGED
@@ -66,6 +66,12 @@ interface AgentCreateParams {
66
66
  amd_enabled?: boolean;
67
67
  /** Keypad digits instead of speech. Three-state: true/false explicit, null = not set (a number's own setting decides). */
68
68
  dtmf_enabled?: boolean | null;
69
+ /** Leave a message on detected voicemails. Applies to DASHBOARD-imported numbers on
70
+ * this agent; API-imported numbers use their own per-number setting instead. Enabling
71
+ * without voicemail_message is rejected with voicemail_message_required. */
72
+ voicemail_leave_enabled?: boolean;
73
+ /** Spoken word for word on voicemail when enabled - the agent never rewrites it. */
74
+ voicemail_message?: string | null;
69
75
  /** Where to POST post-call data. */
70
76
  webhook_url?: string | null;
71
77
  /** Agent can end the call cleanly. Default true. */
@@ -124,6 +130,8 @@ interface Agent {
124
130
  fallback_message: string;
125
131
  post_call_sms_enabled?: boolean;
126
132
  post_call_sms_template?: string | null;
133
+ voicemail_leave_enabled?: boolean;
134
+ voicemail_message?: string | null;
127
135
  data_extraction_fields?: unknown[];
128
136
  is_active: boolean;
129
137
  created_at: string;
@@ -385,6 +393,12 @@ interface PhoneNumber {
385
393
  custom_prompt?: string | null;
386
394
  voice_id?: string | null;
387
395
  sms_reply_enabled?: boolean;
396
+ /** This number's own voicemail setting - the ONLY one that applies to API-imported
397
+ * numbers (dashboard-imported numbers follow the agent). null = not set = silent
398
+ * hangup on voicemail. */
399
+ voicemail_leave_enabled?: boolean | null;
400
+ /** Spoken word for word on a detected voicemail when enabled. */
401
+ voicemail_message?: string | null;
388
402
  sms_prompt?: string | null;
389
403
  web_prompt?: string | null;
390
404
  speaking_rate?: number | null;
@@ -401,6 +415,12 @@ interface PhoneNumberUpdateParams {
401
415
  voice_id?: string | null;
402
416
  /** SMS agent auto-reply on/off. Default false. */
403
417
  sms_reply_enabled?: boolean;
418
+ /** This number's own voicemail toggle - the only voicemail control for API-imported
419
+ * numbers. Enabling without a message (here or already saved) is rejected with
420
+ * voicemail_message_required. null clears. */
421
+ voicemail_leave_enabled?: boolean | null;
422
+ /** Spoken word for word on voicemail. Max 2000. null clears. */
423
+ voicemail_message?: string | null;
404
424
  /** SMS agent instructions (independent channel). Max 20000. null clears. */
405
425
  sms_prompt?: string | null;
406
426
  /** Web agent instructions (independent channel). Max 20000. null clears. */
@@ -556,6 +576,38 @@ interface WebhookConfigResponse {
556
576
  phone_number?: string;
557
577
  url?: string | null;
558
578
  }
579
+ /** Your own S3-compatible recording storage (BYO storage). */
580
+ interface StorageConfig {
581
+ storage_enabled: boolean;
582
+ endpoint: string | null;
583
+ region: string | null;
584
+ bucket: string | null;
585
+ access_key: string | null;
586
+ }
587
+ interface StorageSetParams {
588
+ /** The exact bucket name at your provider. */
589
+ bucket: string;
590
+ /** Access key ID with permission to write objects. */
591
+ access_key: string;
592
+ /** Secret access key. Write-only - stored encrypted, never returned. */
593
+ secret_key: string;
594
+ /** https:// endpoint of your provider. Leave empty for Amazon S3. */
595
+ endpoint?: string;
596
+ /** Your bucket's region. Defaults to auto. */
597
+ region?: string;
598
+ }
599
+ interface StorageSetResponse {
600
+ ok: boolean;
601
+ storage_enabled: boolean;
602
+ bucket: string;
603
+ endpoint: string | null;
604
+ region: string;
605
+ verified: boolean;
606
+ }
607
+ interface StorageDeleteResponse {
608
+ ok: boolean;
609
+ storage_enabled: boolean;
610
+ }
559
611
 
560
612
  declare class PhoneNumbers {
561
613
  private readonly http;
@@ -643,6 +695,21 @@ declare class UsageResource {
643
695
  get(opts?: RequestOptions): Promise<Usage>;
644
696
  }
645
697
 
698
+ declare class Storage {
699
+ private readonly http;
700
+ constructor(http: HttpClient);
701
+ /** Connect your own S3-compatible bucket for call recordings (data residency).
702
+ * The connection is verified with a probe write BEFORE saving - broken
703
+ * credentials are rejected, never stored. Recordings then upload to your
704
+ * bucket and Nixflex keeps no copy; recording_url becomes a byo: path. */
705
+ set(params: StorageSetParams, opts?: RequestOptions): Promise<StorageSetResponse>;
706
+ /** Current storage configuration. The secret is never included. */
707
+ get(opts?: RequestOptions): Promise<StorageConfig>;
708
+ /** Disconnect and clear. Recordings return to Nixflex EU storage from the
709
+ * next call; files already in your bucket are untouched - they are yours. */
710
+ delete(opts?: RequestOptions): Promise<StorageDeleteResponse>;
711
+ }
712
+
646
713
  declare class Webhooks {
647
714
  private readonly http;
648
715
  constructor(http: HttpClient);
@@ -732,6 +799,8 @@ declare class Nixflex {
732
799
  readonly usage: UsageResource;
733
800
  /** Per-number post-call webhook configuration. */
734
801
  readonly webhooks: Webhooks;
802
+ /** Your own S3-compatible recording storage (data residency). */
803
+ readonly storage: Storage;
735
804
  constructor(options: NixflexClientOptions);
736
805
  /** Create a brand-new API key (unauthenticated signup endpoint - most
737
806
  * developers use the dashboard instead). The key_secret is shown ONCE.
@@ -742,4 +811,4 @@ declare class Nixflex {
742
811
  }, baseUrl?: string): Promise<KeyCreateResponse>;
743
812
  }
744
813
 
745
- export { type Agent, type AgentCreateParams, type AgentDeleteResponse, type AgentUpdateParams, type BatchCampaignParams, type BatchCreateResponse, type BatchInvalidEntry, type BatchLaunchResponse, type BatchRecipient, type Call, type CallDeleteAllResponse, type CallDeleteResponse, type CallDirection, type CallerSentiment, type KeyCreateResponse, type KeyRotateResponse, type ListParams, type MonitorToggleResponse, Nixflex, type NixflexAPIErrorBody, NixflexAuthenticationError, type NixflexClientOptions, NixflexConnectionError, NixflexError, NixflexInvalidRequestError, NixflexNotFoundError, NixflexPaymentRequiredError, NixflexRateLimitError, NixflexServerError, type OutboundCallParams, type OutboundCallResponse, type PhoneNumber, type PhoneNumberDeleteResponse, type PhoneNumberImportParams, type PhoneNumberListResponse, type PhoneNumberUpdateParams, type RequestOptions, type ResponseLength, type SmsCampaign, type SmsCampaignCreateParams, type SmsCampaignDeleteResponse, type SmsCampaignLaunchResponse, type SmsCampaignListResponse, type SmsCampaignRecipient, type SmsCampaignStatus, type SmsSendParams, type SmsSendResponse, type TransferType, type Usage, type VerifyOptions, type WebCallsToggleResponse, type WebhookConfigResponse, type Weekday, Nixflex as default, errorFromResponse, verifyWebhookSignature };
814
+ export { type Agent, type AgentCreateParams, type AgentDeleteResponse, type AgentUpdateParams, type BatchCampaignParams, type BatchCreateResponse, type BatchInvalidEntry, type BatchLaunchResponse, type BatchRecipient, type Call, type CallDeleteAllResponse, type CallDeleteResponse, type CallDirection, type CallerSentiment, type KeyCreateResponse, type KeyRotateResponse, type ListParams, type MonitorToggleResponse, Nixflex, type NixflexAPIErrorBody, NixflexAuthenticationError, type NixflexClientOptions, NixflexConnectionError, NixflexError, NixflexInvalidRequestError, NixflexNotFoundError, NixflexPaymentRequiredError, NixflexRateLimitError, NixflexServerError, type OutboundCallParams, type OutboundCallResponse, type PhoneNumber, type PhoneNumberDeleteResponse, type PhoneNumberImportParams, type PhoneNumberListResponse, type PhoneNumberUpdateParams, type RequestOptions, type ResponseLength, type SmsCampaign, type SmsCampaignCreateParams, type SmsCampaignDeleteResponse, type SmsCampaignLaunchResponse, type SmsCampaignListResponse, type SmsCampaignRecipient, type SmsCampaignStatus, type SmsSendParams, type SmsSendResponse, type StorageConfig, type StorageDeleteResponse, type StorageSetParams, type StorageSetResponse, type TransferType, type Usage, type VerifyOptions, type WebCallsToggleResponse, type WebhookConfigResponse, type Weekday, Nixflex as default, errorFromResponse, verifyWebhookSignature };
package/dist/index.js CHANGED
@@ -429,6 +429,28 @@ var UsageResource = class {
429
429
  return this.http.request("GET", "/usage", void 0, void 0, opts);
430
430
  }
431
431
  };
432
+ var Storage = class {
433
+ constructor(http) {
434
+ this.http = http;
435
+ }
436
+ http;
437
+ /** Connect your own S3-compatible bucket for call recordings (data residency).
438
+ * The connection is verified with a probe write BEFORE saving - broken
439
+ * credentials are rejected, never stored. Recordings then upload to your
440
+ * bucket and Nixflex keeps no copy; recording_url becomes a byo: path. */
441
+ set(params, opts) {
442
+ return this.http.request("PUT", "/account/storage", params, void 0, opts);
443
+ }
444
+ /** Current storage configuration. The secret is never included. */
445
+ get(opts) {
446
+ return this.http.request("GET", "/account/storage", void 0, void 0, opts);
447
+ }
448
+ /** Disconnect and clear. Recordings return to Nixflex EU storage from the
449
+ * next call; files already in your bucket are untouched - they are yours. */
450
+ delete(opts) {
451
+ return this.http.request("DELETE", "/account/storage", void 0, void 0, opts);
452
+ }
453
+ };
432
454
  var Webhooks = class {
433
455
  constructor(http) {
434
456
  this.http = http;
@@ -476,6 +498,8 @@ var Nixflex = class {
476
498
  usage;
477
499
  /** Per-number post-call webhook configuration. */
478
500
  webhooks;
501
+ /** Your own S3-compatible recording storage (data residency). */
502
+ storage;
479
503
  constructor(options) {
480
504
  const http = new HttpClient(options);
481
505
  this.agents = new Agents(http);
@@ -486,6 +510,7 @@ var Nixflex = class {
486
510
  this.keys = new Keys(http);
487
511
  this.usage = new UsageResource(http);
488
512
  this.webhooks = new Webhooks(http);
513
+ this.storage = new Storage(http);
489
514
  }
490
515
  /** Create a brand-new API key (unauthenticated signup endpoint - most
491
516
  * developers use the dashboard instead). The key_secret is shown ONCE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nixflex",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Official Node.js SDK for the Nixflex voice AI platform - AI phone agents, outbound campaigns, and SMS.",
5
5
  "keywords": [
6
6
  "nixflex",