Well, I figured this out! The API documentation is incomplete and just flat out wrong, but through trial and error I got this working. The trick is to use the wix.bookings.frontend functions that are normally used by a logged in user when booking a session.
First, you need to find at least one upcoming session of the service you are interested in. This must be done in a backend module. Something like this:
-
Use services.queryServices() to find one or more services that you are interested in finding the user’s sessions remaining relative to. [See wix-bookings.v2]
-
Get the schedule IDs associated with those services.
-
Find an upcoming session on that schedule, using sessions.querySessions(). Use .hasSome(“scheduleId”, [ ]). .ge(“end.timestamp”, new Date()).limit(1) to specify the schedule on your desired service and only return the first future session. [See wix-bookings-backend]
Once you have the upcoming session, you will need to find the contact(s) for which you need to determine the sessions remaining for the contact’s pricing plan relative to that session. I used contacts.querryContacts(), which is another backend function.
The rest of this is done on the frontend, on a dashboard page. The functions are defined in wix-bookings-frontend.
First you need to convert the session to a slot. To do this you use getServiceAvailability(). The first parameter is the ID of the service, retrieved by the backend function described above. The second parameter includes the start and end time of the session from above. This function returns a list of slots, but there should only be one in the list, and I just look at the id of the first element in the returned array.
Now, you can use getCheckoutOptions() from the same module. It takes two parameters. The first is the slot ID, and I just use the ID from the [0] element of the slot array. The second parameter is described in the documentation as userId. I could find no documentation for this. In fact, the example code suggests importing WixUsers from ‘wix-users’, and this module doesn’t seem to exist, nor is there any documentation for it. I used contactId here and it seems to work. [FYI, I’ve also found that contactId and memberId seem to be identical for site members, so I think you can use them interchangeably.]
The documentation says that this function returns an array of type checkoutOptions. The documentation is wrong. If you try to reference the elements of that array your code will fail. Instead of checkoutOptions[i], you must specify checkoutOptions.checkoutMethods[i]. The code editor will flag this as an error, saying “property checkoutMethods does not exist on type ‘checkoutOption[ ]’.” Ignore this error, and the code should work. (It does for me.)
The elements in this array specify all of the ways that the specified user can pay for the specified session. When the type field of the checkoutMethod is “package”, it means that a package-type pricing plan is available. In that case, the object also includes fields such as planName, totalCredits, and remainingCredits, which were the whole reason I went down this rabbit hole.
I hope this works for anyone else who needs this feature.