@unboundcx/sdk 4.13.20 → 4.13.22

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.13.20",
3
+ "version": "4.13.22",
4
4
  "description": "Official JavaScript SDK for the Unbound API - A comprehensive toolkit for integrating with Unbound's communication, AI, and data management services",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -17,6 +17,8 @@ export class SmsService {
17
17
  * @param {Object} [params.variables] - Template variables
18
18
  * @param {Array<string>} [params.mediaUrls] - Media URLs for MMS
19
19
  * @param {string} [params.webhookUrl] - Webhook URL for delivery status
20
+ * @param {string} [params.relatedId] - Task/engagement (or other record) id
21
+ * to attach this message to, so it surfaces on that record's feed
20
22
  * @returns {Promise<Object>} Message details
21
23
  */
22
24
  async send({
@@ -27,6 +29,7 @@ export class SmsService {
27
29
  variables,
28
30
  mediaUrls,
29
31
  webhookUrl,
32
+ relatedId,
30
33
  }) {
31
34
  const messageData = {};
32
35
  if (from) messageData.from = from;
@@ -35,6 +38,7 @@ export class SmsService {
35
38
  if (variables) messageData.variables = variables;
36
39
  if (mediaUrls) messageData.mediaUrls = mediaUrls;
37
40
  if (webhookUrl) messageData.webhookUrl = webhookUrl;
41
+ if (relatedId) messageData.relatedId = relatedId;
38
42
 
39
43
  this.sdk.validateParams(
40
44
  { to, ...messageData },
@@ -46,6 +50,7 @@ export class SmsService {
46
50
  variables: { type: 'object', required: false },
47
51
  mediaUrls: { type: 'array', required: false },
48
52
  webhookUrl: { type: 'string', required: false },
53
+ relatedId: { type: 'string', required: false },
49
54
  },
50
55
  );
51
56
 
@@ -73,4 +78,26 @@ export class SmsService {
73
78
  const result = await internalRequest(this.sdk, `/messaging/sms/${id}`, 'GET');
74
79
  return result;
75
80
  }
81
+
82
+ /**
83
+ * List SMS/MMS messages tied to a task/engagement (or other record) id —
84
+ * feed read path for the contact-center interaction timeline.
85
+ * @param {string} relatedId - Related record id
86
+ * @returns {Promise<Object>} { messages: [...] }
87
+ */
88
+ async getByRelated(relatedId) {
89
+ this.sdk.validateParams(
90
+ { relatedId },
91
+ {
92
+ relatedId: { type: 'string', required: true },
93
+ },
94
+ );
95
+
96
+ const result = await internalRequest(
97
+ this.sdk,
98
+ `/messaging/sms/related/${relatedId}`,
99
+ 'GET',
100
+ );
101
+ return result;
102
+ }
76
103
  }
@@ -86,6 +86,26 @@ export class PortalsService {
86
86
  * @param {string} [updates.name] - New display name for the portal.
87
87
  * @param {string} [updates.domain] - New custom domain for the portal.
88
88
  * @param {object} [updates.settings] - Updated portal configuration settings.
89
+ * @param {object} [updates.settings.profile] - P11.2: visitor-editable
90
+ * profile fields. `{ people: { enabled, fields: [{ name, editable }] },
91
+ * company: { enabled, fields: [{ name, editable }], editorMode,
92
+ * editorFilter } }`. `fields` (max 40 each) is the allowlist of
93
+ * people/company columns exposed on the portal's `GET /portal-profile` —
94
+ * never system columns (id/*At/*By/isDeleted/recordTypeId), foreign
95
+ * keys, or encrypted fields (the API 400s on save otherwise).
96
+ * `company.editorMode` is `'none'|'all'|'rules'` — whether a signed-in
97
+ * visitor may edit their OWN company record: nobody / everyone signed
98
+ * in / only people matching `editorFilter` (same `{'<field>::<op>':
99
+ * value}` AND-map as `settings.peopleFilter`, ≥1 rule required for
100
+ * `'rules'`). A per-person override (people custom field
101
+ * `portalCompanyEdit__c`, `'allow'|'deny'`, set via `sdk.objects.update`)
102
+ * wins over `editorMode`/`editorFilter` when present.
103
+ * @param {string} [updates.settings.companyTicketsMode] - `'none'|'all'|'rules'`
104
+ * — successor to the legacy `settings.companyTickets` boolean
105
+ * (`true`→`'all'`, `false`→`'none'`); same 3-way shape as
106
+ * `settings.profile.company.editorMode` above, paired with
107
+ * `settings.companyTicketsFilter`. Prefer this over the boolean going
108
+ * forward — both may be sent, `companyTicketsMode` wins.
89
109
  * @param {boolean} [updates.isPublic] - Updated public accessibility flag.
90
110
  * @param {string} [updates.customCss] - Updated custom CSS for the portal.
91
111
  * @param {string} [updates.customJs] - Updated custom JavaScript for the portal.
@@ -572,16 +592,31 @@ export class PortalsService {
572
592
  }
573
593
 
574
594
  /**
575
- * Staff-only portal credential status for a person. Never includes hashes.
595
+ * Staff-only portal credential + access status for a person. Never
596
+ * includes hashes or tokens.
576
597
  *
577
598
  * @param {string} peopleId
578
599
  * @returns {Promise<{
600
+ * status: "none"|"invited"|"active"|"locked",
579
601
  * hasPassword: boolean,
580
602
  * ssoLinked: boolean,
581
603
  * lastLoginAt: string|null,
582
604
  * lastLoginMethod: string|null,
583
- * mustReset: boolean
584
- * }>}
605
+ * mustReset: boolean,
606
+ * invitedAt: string|null,
607
+ * lockedUntil: string|null,
608
+ * portals: Array<{
609
+ * id: string,
610
+ * name: string,
611
+ * kind: "support"|"partner",
612
+ * hostedDomain: string,
613
+ * domain: string|null,
614
+ * matches: boolean
615
+ * }>
616
+ * }>} `portals` lists only support/partner portals on the account (a
617
+ * portal with no login surface, e.g. `marketing`, is never included);
618
+ * `matches` is whether this person currently passes that portal's
619
+ * people-access filter.
585
620
  */
586
621
  async getPeopleAccess(peopleId) {
587
622
  this.sdk.validateParams(
@@ -625,6 +660,106 @@ export class PortalsService {
625
660
  );
626
661
  }
627
662
 
663
+ /**
664
+ * Invites a person to sign in to a support/partner portal: upserts their
665
+ * portal credential (`mustReset=1`), stamps `invitedAt`/`invitedBy`, and
666
+ * sends the account's `portal-welcome` email with a fresh 30-minute
667
+ * single-use set-password link.
668
+ *
669
+ * The person must pass the target portal's people-access filter — see
670
+ * `getPeopleAccess(peopleId).portals[].matches` — or the call 400s.
671
+ *
672
+ * @param {string} peopleId
673
+ * @param {object} params
674
+ * @param {string} params.portalId - The support/partner portal to invite them to.
675
+ * @returns {Promise<{
676
+ * status: "invited",
677
+ * hasPassword: boolean,
678
+ * ssoLinked: boolean,
679
+ * lastLoginAt: string|null,
680
+ * lastLoginMethod: string|null,
681
+ * mustReset: boolean,
682
+ * invitedAt: string,
683
+ * lockedUntil: string|null
684
+ * }>}
685
+ */
686
+ async invitePerson(peopleId, { portalId }) {
687
+ this.sdk.validateParams(
688
+ { peopleId, portalId },
689
+ {
690
+ peopleId: { type: "string", required: true },
691
+ portalId: { type: "string", required: true },
692
+ },
693
+ );
694
+
695
+ return internalRequest(
696
+ this.sdk,
697
+ `/portals/people/${encodeURIComponent(peopleId)}/invite`,
698
+ "POST",
699
+ { body: { portalId } },
700
+ );
701
+ }
702
+
703
+ /**
704
+ * Sends a person a fresh password-reset email for a support/partner
705
+ * portal (the account's `portal-password-reset` template) with a new
706
+ * 30-minute single-use set-password link. Works whether they were
707
+ * previously invited or already active.
708
+ *
709
+ * @param {string} peopleId
710
+ * @param {object} params
711
+ * @param {string} params.portalId - The support/partner portal to send the reset for.
712
+ * @returns {Promise<{
713
+ * status: "none"|"invited"|"active"|"locked",
714
+ * hasPassword: boolean,
715
+ * ssoLinked: boolean,
716
+ * lastLoginAt: string|null,
717
+ * lastLoginMethod: string|null,
718
+ * mustReset: boolean,
719
+ * invitedAt: string|null,
720
+ * lockedUntil: string|null
721
+ * }>}
722
+ */
723
+ async resetPersonPassword(peopleId, { portalId }) {
724
+ this.sdk.validateParams(
725
+ { peopleId, portalId },
726
+ {
727
+ peopleId: { type: "string", required: true },
728
+ portalId: { type: "string", required: true },
729
+ },
730
+ );
731
+
732
+ return internalRequest(
733
+ this.sdk,
734
+ `/portals/people/${encodeURIComponent(peopleId)}/reset-password`,
735
+ "POST",
736
+ { body: { portalId } },
737
+ );
738
+ }
739
+
740
+ /**
741
+ * Revokes a person's portal access (soft-deletes their credential across
742
+ * every portal on the account). Idempotent — revoking someone with no
743
+ * credential is a no-op, not an error.
744
+ *
745
+ * @param {string} peopleId
746
+ * @returns {Promise<{ ok: true }>}
747
+ */
748
+ async revokePeopleAccess(peopleId) {
749
+ this.sdk.validateParams(
750
+ { peopleId },
751
+ {
752
+ peopleId: { type: "string", required: true },
753
+ },
754
+ );
755
+
756
+ return internalRequest(
757
+ this.sdk,
758
+ `/portals/people/${encodeURIComponent(peopleId)}/access`,
759
+ "DELETE",
760
+ );
761
+ }
762
+
628
763
  /**
629
764
  * Lists the customer-facing labels configured for each engagement status.
630
765
  *