@unboundcx/sdk 4.13.20 → 4.13.21

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 (2) hide show
  1. package/package.json +1 -1
  2. package/services/portals.js +118 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unboundcx/sdk",
3
- "version": "4.13.20",
3
+ "version": "4.13.21",
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",
@@ -572,16 +572,31 @@ export class PortalsService {
572
572
  }
573
573
 
574
574
  /**
575
- * Staff-only portal credential status for a person. Never includes hashes.
575
+ * Staff-only portal credential + access status for a person. Never
576
+ * includes hashes or tokens.
576
577
  *
577
578
  * @param {string} peopleId
578
579
  * @returns {Promise<{
580
+ * status: "none"|"invited"|"active"|"locked",
579
581
  * hasPassword: boolean,
580
582
  * ssoLinked: boolean,
581
583
  * lastLoginAt: string|null,
582
584
  * lastLoginMethod: string|null,
583
- * mustReset: boolean
584
- * }>}
585
+ * mustReset: boolean,
586
+ * invitedAt: string|null,
587
+ * lockedUntil: string|null,
588
+ * portals: Array<{
589
+ * id: string,
590
+ * name: string,
591
+ * kind: "support"|"partner",
592
+ * hostedDomain: string,
593
+ * domain: string|null,
594
+ * matches: boolean
595
+ * }>
596
+ * }>} `portals` lists only support/partner portals on the account (a
597
+ * portal with no login surface, e.g. `marketing`, is never included);
598
+ * `matches` is whether this person currently passes that portal's
599
+ * people-access filter.
585
600
  */
586
601
  async getPeopleAccess(peopleId) {
587
602
  this.sdk.validateParams(
@@ -625,6 +640,106 @@ export class PortalsService {
625
640
  );
626
641
  }
627
642
 
643
+ /**
644
+ * Invites a person to sign in to a support/partner portal: upserts their
645
+ * portal credential (`mustReset=1`), stamps `invitedAt`/`invitedBy`, and
646
+ * sends the account's `portal-welcome` email with a fresh 30-minute
647
+ * single-use set-password link.
648
+ *
649
+ * The person must pass the target portal's people-access filter — see
650
+ * `getPeopleAccess(peopleId).portals[].matches` — or the call 400s.
651
+ *
652
+ * @param {string} peopleId
653
+ * @param {object} params
654
+ * @param {string} params.portalId - The support/partner portal to invite them to.
655
+ * @returns {Promise<{
656
+ * status: "invited",
657
+ * hasPassword: boolean,
658
+ * ssoLinked: boolean,
659
+ * lastLoginAt: string|null,
660
+ * lastLoginMethod: string|null,
661
+ * mustReset: boolean,
662
+ * invitedAt: string,
663
+ * lockedUntil: string|null
664
+ * }>}
665
+ */
666
+ async invitePerson(peopleId, { portalId }) {
667
+ this.sdk.validateParams(
668
+ { peopleId, portalId },
669
+ {
670
+ peopleId: { type: "string", required: true },
671
+ portalId: { type: "string", required: true },
672
+ },
673
+ );
674
+
675
+ return internalRequest(
676
+ this.sdk,
677
+ `/portals/people/${encodeURIComponent(peopleId)}/invite`,
678
+ "POST",
679
+ { body: { portalId } },
680
+ );
681
+ }
682
+
683
+ /**
684
+ * Sends a person a fresh password-reset email for a support/partner
685
+ * portal (the account's `portal-password-reset` template) with a new
686
+ * 30-minute single-use set-password link. Works whether they were
687
+ * previously invited or already active.
688
+ *
689
+ * @param {string} peopleId
690
+ * @param {object} params
691
+ * @param {string} params.portalId - The support/partner portal to send the reset for.
692
+ * @returns {Promise<{
693
+ * status: "none"|"invited"|"active"|"locked",
694
+ * hasPassword: boolean,
695
+ * ssoLinked: boolean,
696
+ * lastLoginAt: string|null,
697
+ * lastLoginMethod: string|null,
698
+ * mustReset: boolean,
699
+ * invitedAt: string|null,
700
+ * lockedUntil: string|null
701
+ * }>}
702
+ */
703
+ async resetPersonPassword(peopleId, { portalId }) {
704
+ this.sdk.validateParams(
705
+ { peopleId, portalId },
706
+ {
707
+ peopleId: { type: "string", required: true },
708
+ portalId: { type: "string", required: true },
709
+ },
710
+ );
711
+
712
+ return internalRequest(
713
+ this.sdk,
714
+ `/portals/people/${encodeURIComponent(peopleId)}/reset-password`,
715
+ "POST",
716
+ { body: { portalId } },
717
+ );
718
+ }
719
+
720
+ /**
721
+ * Revokes a person's portal access (soft-deletes their credential across
722
+ * every portal on the account). Idempotent — revoking someone with no
723
+ * credential is a no-op, not an error.
724
+ *
725
+ * @param {string} peopleId
726
+ * @returns {Promise<{ ok: true }>}
727
+ */
728
+ async revokePeopleAccess(peopleId) {
729
+ this.sdk.validateParams(
730
+ { peopleId },
731
+ {
732
+ peopleId: { type: "string", required: true },
733
+ },
734
+ );
735
+
736
+ return internalRequest(
737
+ this.sdk,
738
+ `/portals/people/${encodeURIComponent(peopleId)}/access`,
739
+ "DELETE",
740
+ );
741
+ }
742
+
628
743
  /**
629
744
  * Lists the customer-facing labels configured for each engagement status.
630
745
  *