@sentdm/sentdm 0.38.0 → 0.39.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.
@@ -336,6 +336,282 @@ export interface APIResponseWebhook {
336
336
  success?: boolean;
337
337
  }
338
338
 
339
+ /**
340
+ * The envelope Sent POSTs to a subscribed webhook endpoint. Every event shares
341
+ * this shape and varies only in Payload.
342
+ */
343
+ export interface ChannelEvent {
344
+ /**
345
+ * The specific event within the family, for example message.delivered,
346
+ * message.received or contact.opt_out. Absent on events that have no subtype, so
347
+ * treat it as optional.
348
+ */
349
+ event?: string | null;
350
+
351
+ /**
352
+ * The event family, for example message, templates or contact. Route on this
353
+ * first, then on event for the specific change.
354
+ */
355
+ field?: string;
356
+
357
+ /**
358
+ * Body of a channel event: where one of the customer's channels stands in
359
+ * provisioning and compliance. Delivered when a milestone moves — a registration
360
+ * filed, a verdict returned, a resubmission asked for, a sender gone live — so a
361
+ * customer's own onboarding UI does not have to poll GET /v3/channels.
362
+ *
363
+ * The subject is one item, never the account. A customer's "SMS channel" has no
364
+ * status; a market does. Country, NumberType and SenderValue name which one, so a
365
+ * customer terminating only to Kosovo never receives an event about US 10DLC.
366
+ *
367
+ * Status is the stable half of the contract. It is the same four-value set GET
368
+ * /v3/channels publishes, computed through the same code, so an event and a read
369
+ * of the same market cannot disagree. A subscriber that reads nothing but the
370
+ * status and the subject fields is a correct subscriber. The sub-type on the
371
+ * envelope names the specific milestone and is additive — that vocabulary comes
372
+ * from registries and carriers, which are parties Sent does not control.
373
+ *
374
+ * Status means provisioning and compliance are complete, not that a send will
375
+ * succeed right now. An account can be suspended, or a destination blocked by a
376
+ * routing rule, without either showing up here. Those are separate surfaces and
377
+ * deliberately not modelled on this payload.
378
+ */
379
+ payload?: ChannelEventPayload | null;
380
+
381
+ /**
382
+ * The event-specific body.
383
+ */
384
+ request_id?: string | null;
385
+
386
+ /**
387
+ * When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
388
+ * time, not the time the underlying change happened. Use the timestamp inside the
389
+ * payload for the latter.
390
+ */
391
+ timestamp?: string;
392
+ }
393
+
394
+ /**
395
+ * Body of a channel event: where one of the customer's channels stands in
396
+ * provisioning and compliance. Delivered when a milestone moves — a registration
397
+ * filed, a verdict returned, a resubmission asked for, a sender gone live — so a
398
+ * customer's own onboarding UI does not have to poll GET /v3/channels.
399
+ *
400
+ * The subject is one item, never the account. A customer's "SMS channel" has no
401
+ * status; a market does. Country, NumberType and SenderValue name which one, so a
402
+ * customer terminating only to Kosovo never receives an event about US 10DLC.
403
+ *
404
+ * Status is the stable half of the contract. It is the same four-value set GET
405
+ * /v3/channels publishes, computed through the same code, so an event and a read
406
+ * of the same market cannot disagree. A subscriber that reads nothing but the
407
+ * status and the subject fields is a correct subscriber. The sub-type on the
408
+ * envelope names the specific milestone and is additive — that vocabulary comes
409
+ * from registries and carriers, which are parties Sent does not control.
410
+ *
411
+ * Status means provisioning and compliance are complete, not that a send will
412
+ * succeed right now. An account can be suspended, or a destination blocked by a
413
+ * routing rule, without either showing up here. Those are separate surfaces and
414
+ * deliberately not modelled on this payload.
415
+ */
416
+ export interface ChannelEventPayload {
417
+ /**
418
+ * The market's destination country as an ISO 3166-1 alpha-2 code, for example XK.
419
+ * Always present, and the property that identifies this payload among the
420
+ * delivered envelopes — see DeliveredWebhookEvents. Every event in this family
421
+ * reports one market, and a market has a country.
422
+ */
423
+ country: string;
424
+
425
+ /**
426
+ * The account whose market this is, named as on every other family. When an
427
+ * organization receives an event for one of its sender profiles this is the
428
+ * profile, so a reseller compares it with its own id and anything different is one
429
+ * of its profiles.
430
+ */
431
+ account_id?: string;
432
+
433
+ /**
434
+ * The channel this market belongs to: sms, whatsapp, or rcs. Never sent — that
435
+ * value belongs to message events, where it names the smart-routing brand rather
436
+ * than a channel that can be provisioned.
437
+ */
438
+ channel?: string;
439
+
440
+ /**
441
+ * The kind of sender the market uses, for example TEN_DLC, LOCAL, or ALPHANUMERIC.
442
+ * Omitted when the subject has no sender type of its own.
443
+ */
444
+ number_type?: string | null;
445
+
446
+ /**
447
+ * Why the market reached this state, when a reason was given — a correction
448
+ * explained, or a campaign lapse. Free text, passed through from the registry or
449
+ * carrier that wrote it, so treat it as a message to show a human rather than a
450
+ * value to branch on.
451
+ */
452
+ reason?: string | null;
453
+
454
+ /**
455
+ * The sender itself — a number in E.164, or an alphanumeric sender ID.
456
+ *
457
+ * Always present, and null until a sender exists. The key is on every delivery so
458
+ * a subscriber reads one shape rather than branching on whether the field arrived
459
+ * — the same choice template_id makes on the message payload.
460
+ *
461
+ * It can carry a value at any point in the lifecycle, not only once the market is
462
+ * live: a number ordered and not yet active at the carrier is already known during
463
+ * PROVISIONING, and an alphanumeric sender the customer chose themselves is known
464
+ * before anything is filed. It is null while the market is still waiting on a
465
+ * number, which for a US 10DLC registration is every event up to
466
+ * channel.activated.
467
+ */
468
+ sender_value?: string | null;
469
+
470
+ /**
471
+ * Where the market stands: PENDING_REVIEW, ACTION_NEEDED, PROVISIONING, ACTIVE or
472
+ * INACTIVE. PENDING_REVIEW means a registry or a carrier holds it and the wait is
473
+ * theirs; ACTION_NEEDED means it is yours; PROVISIONING means the verdict is in
474
+ * and Sent is acquiring the sender; INACTIVE means it had a working sender and no
475
+ * longer does.
476
+ *
477
+ * Each event name is the transition into one of these, but the two are separate
478
+ * fields and may legitimately differ. A resubmission filed against a market whose
479
+ * sender is already live is channel.submitted carrying ACTIVE: a correction is
480
+ * with the registry and the sender keeps working. Read both.
481
+ */
482
+ status?: string;
483
+
484
+ /**
485
+ * When the transition happened, in UTC (yyyy-MM-ddTHH:mm:ssZ).
486
+ */
487
+ updated_at?: string;
488
+ }
489
+
490
+ /**
491
+ * The envelope Sent POSTs to a subscribed webhook endpoint. Every event shares
492
+ * this shape and varies only in Payload.
493
+ */
494
+ export interface ContactEvent {
495
+ /**
496
+ * The specific event within the family, for example message.delivered,
497
+ * message.received or contact.opt_out. Absent on events that have no subtype, so
498
+ * treat it as optional.
499
+ */
500
+ event?: string | null;
501
+
502
+ /**
503
+ * The event family, for example message, templates or contact. Route on this
504
+ * first, then on event for the specific change.
505
+ */
506
+ field?: string;
507
+
508
+ /**
509
+ * Body of a contact.opt_in, contact.opt_out or contact.help event. Delivered when
510
+ * a contact signals a consent change or asks for help.
511
+ *
512
+ * These events state the signal outright, so you do not have to recognise keywords
513
+ * in the text of a message.received event. They also cover cases that produce no
514
+ * inbound message at all, such as a network handling an opt-out on your behalf.
515
+ *
516
+ * Fields are ordered identity → resulting state → provenance → join key. Nothing
517
+ * here restates the envelope: which of the three signals occurred is the
518
+ * envelope's event, and when it was emitted is its timestamp. Retries carry the
519
+ * same X-Webhook-Event-ID header, which is what to deduplicate on.
520
+ */
521
+ payload?: ContactEventPayload | null;
522
+
523
+ /**
524
+ * The event-specific body.
525
+ */
526
+ request_id?: string | null;
527
+
528
+ /**
529
+ * When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
530
+ * time, not the time the underlying change happened. Use the timestamp inside the
531
+ * payload for the latter.
532
+ */
533
+ timestamp?: string;
534
+ }
535
+
536
+ /**
537
+ * Body of a contact.opt_in, contact.opt_out or contact.help event. Delivered when
538
+ * a contact signals a consent change or asks for help.
539
+ *
540
+ * These events state the signal outright, so you do not have to recognise keywords
541
+ * in the text of a message.received event. They also cover cases that produce no
542
+ * inbound message at all, such as a network handling an opt-out on your behalf.
543
+ *
544
+ * Fields are ordered identity → resulting state → provenance → join key. Nothing
545
+ * here restates the envelope: which of the three signals occurred is the
546
+ * envelope's event, and when it was emitted is its timestamp. Retries carry the
547
+ * same X-Webhook-Event-ID header, which is what to deduplicate on.
548
+ */
549
+ export interface ContactEventPayload {
550
+ /**
551
+ * Whether the contact is opted out after this signal — the state to write to your
552
+ * own record. Same meaning as opt_out on the contact resource. On contact.help
553
+ * this reports the contact's existing state, which help does not change.
554
+ *
555
+ * Two signals from the same contact can arrive out of order, because each one is
556
+ * queued on its own rather than against the contact. Compare the envelope's
557
+ * timestamp before you overwrite a newer state with an older one. That timestamp
558
+ * is second-precision, so treat two signals stamped in the same second as
559
+ * unordered and read the contact resource to settle them.
560
+ */
561
+ opt_out: boolean;
562
+
563
+ /**
564
+ * How the signal reached us. INBOUND_KEYWORD means the contact sent a message
565
+ * whose text matched one of the keywords; PROVIDER_SIGNAL means the network
566
+ * reported it. A provider signal usually carries no message_id or text, so read
567
+ * both for null rather than inferring them from this field.
568
+ */
569
+ source: string;
570
+
571
+ /**
572
+ * The account the contact belongs to. Present so one endpoint can serve several
573
+ * accounts.
574
+ */
575
+ account_id?: string;
576
+
577
+ /**
578
+ * The channel the signal arrived on, for example sms or whatsapp.
579
+ */
580
+ channel?: string;
581
+
582
+ /**
583
+ * The contact who raised the signal. Always populated, including for contact.help
584
+ * from a number you have not messaged before — the contact is created if it does
585
+ * not exist yet, so this identifier is always resolvable against the contacts API.
586
+ */
587
+ contact_id?: string;
588
+
589
+ /**
590
+ * The inbound message that carried the signal, matching message_id on the
591
+ * corresponding message.received event so the two can be joined.
592
+ *
593
+ * Sent as null when the signal did not arrive as a message — for example when a
594
+ * network processed an opt-out on your behalf — and also when the message belongs
595
+ * to a different account than this event, which can happen on a shared WhatsApp
596
+ * number. The field is always present, so read it and check for null rather than
597
+ * checking whether the key exists.
598
+ */
599
+ message_id?: string | null;
600
+
601
+ /**
602
+ * The contact's number in E.164 format. Same value as phone_number on the contact
603
+ * resource.
604
+ */
605
+ phone_number?: string;
606
+
607
+ /**
608
+ * The text the contact sent, for example STOP or UNSUBSCRIBE. Sent as null when
609
+ * the signal did not arrive as text. The field is always present, so read it and
610
+ * check for null rather than checking whether the key exists.
611
+ */
612
+ text?: string | null;
613
+ }
614
+
339
615
  /**
340
616
  * Error information
341
617
  */
@@ -367,15 +643,15 @@ export interface ErrorDetail {
367
643
  */
368
644
  export interface InboundMessageEvent {
369
645
  /**
370
- * The specific event within the family, for example message.delivered or
371
- * message.received. Absent on events that have no subtype, so treat it as
372
- * optional.
646
+ * The specific event within the family, for example message.delivered,
647
+ * message.received or contact.opt_out. Absent on events that have no subtype, so
648
+ * treat it as optional.
373
649
  */
374
650
  event?: string | null;
375
651
 
376
652
  /**
377
- * The event family, for example message or templates. Route on this first, then on
378
- * event for the specific change.
653
+ * The event family, for example message, templates or contact. Route on this
654
+ * first, then on event for the specific change.
379
655
  */
380
656
  field?: string;
381
657
 
@@ -385,6 +661,11 @@ export interface InboundMessageEvent {
385
661
  */
386
662
  payload?: InboundMessageEventPayload | null;
387
663
 
664
+ /**
665
+ * The event-specific body.
666
+ */
667
+ request_id?: string | null;
668
+
388
669
  /**
389
670
  * When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
390
671
  * time, not the time the underlying change happened. Use the timestamp inside the
@@ -448,15 +729,15 @@ export interface InboundMessageEventPayload {
448
729
  */
449
730
  export interface MessageEvent {
450
731
  /**
451
- * The specific event within the family, for example message.delivered or
452
- * message.received. Absent on events that have no subtype, so treat it as
453
- * optional.
732
+ * The specific event within the family, for example message.delivered,
733
+ * message.received or contact.opt_out. Absent on events that have no subtype, so
734
+ * treat it as optional.
454
735
  */
455
736
  event?: string | null;
456
737
 
457
738
  /**
458
- * The event family, for example message or templates. Route on this first, then on
459
- * event for the specific change.
739
+ * The event family, for example message, templates or contact. Route on this
740
+ * first, then on event for the specific change.
460
741
  */
461
742
  field?: string;
462
743
 
@@ -467,6 +748,11 @@ export interface MessageEvent {
467
748
  */
468
749
  payload?: MessageEventPayload | null;
469
750
 
751
+ /**
752
+ * The event-specific body.
753
+ */
754
+ request_id?: string | null;
755
+
470
756
  /**
471
757
  * When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
472
758
  * time, not the time the underlying change happened. Use the timestamp inside the
@@ -498,6 +784,13 @@ export interface MessageEventPayload {
498
784
  */
499
785
  agent_id?: string | null;
500
786
 
787
+ /**
788
+ * The rendered message body, as plain text. Sent as null when we aren't asserting
789
+ * a body for this event. The field is always present, so read it and check for
790
+ * null rather than checking whether the key exists. Truncated to 3072 characters.
791
+ */
792
+ body?: string | null;
793
+
501
794
  /**
502
795
  * The channel the message went out on, for example sms or whatsapp. A message that
503
796
  * falls back to another channel reports the channel actually used.
@@ -598,15 +891,15 @@ export namespace PaginationMeta {
598
891
  */
599
892
  export interface TemplateEvent {
600
893
  /**
601
- * The specific event within the family, for example message.delivered or
602
- * message.received. Absent on events that have no subtype, so treat it as
603
- * optional.
894
+ * The specific event within the family, for example message.delivered,
895
+ * message.received or contact.opt_out. Absent on events that have no subtype, so
896
+ * treat it as optional.
604
897
  */
605
898
  event?: string | null;
606
899
 
607
900
  /**
608
- * The event family, for example message or templates. Route on this first, then on
609
- * event for the specific change.
901
+ * The event family, for example message, templates or contact. Route on this
902
+ * first, then on event for the specific change.
610
903
  */
611
904
  field?: string;
612
905
 
@@ -616,6 +909,11 @@ export interface TemplateEvent {
616
909
  */
617
910
  payload?: TemplateEventPayload | null;
618
911
 
912
+ /**
913
+ * The event-specific body.
914
+ */
915
+ request_id?: string | null;
916
+
619
917
  /**
620
918
  * When Sent emitted the event, in UTC (yyyy-MM-ddTHH:mm:ssZ). This is the emission
621
919
  * time, not the time the underlying change happened. Use the timestamp inside the
@@ -645,15 +943,39 @@ export interface TemplateEventPayload {
645
943
  */
646
944
  account_id?: string;
647
945
 
946
+ /**
947
+ * Which consent keyword this template answers, when it is one of Sent's
948
+ * auto-replies: OPT_IN, OPT_OUT, HELP, or OTHER for a customer-defined keyword.
949
+ *
950
+ * Omitted for an ordinary template, so its presence is the answer to "is this an
951
+ * auto-reply". Sent creates the three compliance auto-replies at signup and they
952
+ * go through review like any other template, so their events arrive mixed in with
953
+ * the customer's own with nothing else to tell them apart.
954
+ *
955
+ * Named for the reader rather than after Template.OptAction, which it is mapped
956
+ * from. The MCP tool result deliberately keeps OptAction, OptKeywords and IsOpt:
957
+ * it mirrors the internal shape on purpose and publishes the keywords too, so
958
+ * renaming one of the three there would leave a surface half in each vocabulary.
959
+ * Two names for one concept, each consistent within its own surface, chosen over a
960
+ * rename that breaks MCP clients silently.
961
+ */
962
+ auto_reply_action?: string | null;
963
+
648
964
  /**
649
965
  * The template's category, for example UTILITY, MARKETING, or AUTHENTICATION.
650
966
  */
651
967
  category?: string;
652
968
 
653
969
  /**
654
- * The channel the template applies to.
970
+ * The channel leg this decision is about, for example whatsapp, sms, or rcs. A
971
+ * template is reviewed per channel and the legs come back independently, so each
972
+ * one reports separately.
973
+ *
974
+ * Omitted when the decision applies to the template as a whole rather than to one
975
+ * leg. That event is the broader news: a template-wide rejection blocks every
976
+ * channel, whatever the individual legs say.
655
977
  */
656
- channel?: string;
978
+ channel?: string | null;
657
979
 
658
980
  /**
659
981
  * The template's language code, for example en_US.
@@ -782,11 +1104,11 @@ export interface WebhookListEventsResponse {
782
1104
 
783
1105
  /**
784
1106
  * The exact event body that was delivered, or attempted, for this record. One of
785
- * the three webhook envelopes: a message status change, an inbound message, or a
786
- * template status change. Read field and event to tell which, the same way your
787
- * endpoint does.
1107
+ * the four webhook envelopes: a message status change, an inbound message, a
1108
+ * template status change, or a contact consent signal. Read field and event to
1109
+ * tell which, the same way your endpoint does.
788
1110
  */
789
- event_data?: MessageEvent | InboundMessageEvent | TemplateEvent;
1111
+ event_data?: MessageEvent | InboundMessageEvent | TemplateEvent | ChannelEvent | ContactEvent;
790
1112
 
791
1113
  event_type?: string;
792
1114
 
@@ -1110,6 +1432,10 @@ export declare namespace Webhooks {
1110
1432
  export {
1111
1433
  type APIMeta as APIMeta,
1112
1434
  type APIResponseWebhook as APIResponseWebhook,
1435
+ type ChannelEvent as ChannelEvent,
1436
+ type ChannelEventPayload as ChannelEventPayload,
1437
+ type ContactEvent as ContactEvent,
1438
+ type ContactEventPayload as ContactEventPayload,
1113
1439
  type ErrorDetail as ErrorDetail,
1114
1440
  type InboundMessageEvent as InboundMessageEvent,
1115
1441
  type InboundMessageEventPayload as InboundMessageEventPayload,
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.38.0'; // x-release-please-version
1
+ export const VERSION = '0.39.0'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.38.0";
1
+ export declare const VERSION = "0.39.0";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.38.0";
1
+ export declare const VERSION = "0.39.0";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.38.0'; // x-release-please-version
4
+ exports.VERSION = '0.39.0'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.38.0'; // x-release-please-version
1
+ export const VERSION = '0.39.0'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map