Skip to main content

Sharing

Sharing is how a second user gets access to nodes in ESP RainMaker Neo. Because access is scoped by group membership, you share a group rather than a node; the recipient gains access to whatever the group contains, and to whatever is added to it later.

Sharing is an invitation, not an immediate grant: the sender creates a request, and the recipient accepts or declines it.

Invite a user

await home.share({
username: "<email-or-phone>",
accessType: "secondary",
});

share(options) returns Promise<ESPAPIResponse>. username is the recipient's email address or E.164 phone number, and accessType is either:

  • "secondary": invite as a member who can see and control
  • "primary": transfer ownership

It throws ESPAPICallValidationError when username is missing or blank.

Called on a subgroup, it shares just that subgroup, which is how you give somebody access to one room rather than the whole home.

An unregistered address answers 404

The API deliberately does not reveal whether an account exists for an address, so a request for an unregistered user fails with a not-found error. Do not present that as "no such user"; the same response covers a mistyped address and an address that simply has not signed up.

Accept or decline an invitation

The recipient reads their pending invitations from the user object:

const requests = await user.listSharingRequests();

for (const request of requests) {
console.log(request.groupId, request.accessType, request.primaryEmail);
await request.accept();
}

listSharingRequests() returns Promise<ESPRMNeoSharingRequest[]>, requests received by this user. Each instance carries the request ID, the groupId and subgroupId it concerns, the accessType on offer, and the sender's primaryUserId, primaryEmail and primaryPhoneNumber so you can show who is asking.

accept() and decline() both return Promise<SuccessResponse>. Accepting grants the access; declining denies it. There is no method to list or cancel requests you sent.

accessType on a request may also be "subentity", which the group-level access type never is; that value appears when the invitation concerns a subgroup rather than a whole group.

See who has access

const info = await home.getSharingInfo();

for (const member of info.users) {
console.log(member.userId, member.email, member.accessType);
}

getSharingInfo() returns Promise<GroupSharingInfo>, whose users array carries userId, email, optional phoneNumber, accessType, and subgroups when access came through a subgroup.

What you see depends on your own access, and the cloud decides that:

Your accessYou see
primaryEvery member
secondaryThe group's primary owners
subgroupThe group's primary owners

So an empty-looking member list on a secondary account is expected, not a failure.

Remove access

await home.removeMember("<user-id>");
await home.leave();

removeMember(userId) returns Promise<ESPAPIResponse> and removes another user. It throws ESPAPICallValidationError when userId is blank or refers to the caller.

leave() removes the calling user. The two are not interchangeable: use leave() for yourself, removeMember() for anyone else. Get your own ID from user.getUserInfo() if you need to filter yourself out of a member list.

A group must always keep at least one primary user, so the last owner can neither be removed nor leave.

Method summary

MethodReturns
group.share(options)ESPAPIResponse
group.getSharingInfo()GroupSharingInfo
group.removeMember(userId)ESPAPIResponse
group.leave()ESPAPIResponse
user.listSharingRequests()ESPRMNeoSharingRequest[]
request.accept()SuccessResponse
request.decline()SuccessResponse