Users & access

h3xed has two layers of people. Accounts are the separate humans you share a server with — each gets their own login and the libraries you choose. Profiles are sub-users under a single account, like Netflix, with their own watch state and optional kids restrictions. On top of that, friends, watch party, and co-op let you connect with other people's servers.

Inviting people to your server

The recommended way to give someone their own access is an invite. From the admin panel (/app/) or the desktop app:

  1. Create an invite and choose which libraries it grants
  2. Send the person the invite link
  3. They open it and sign up (or sign in) with an h3xed.app account
  4. Your server shows up in their app automatically, with the libraries you shared

Invites can be created, listed, and revoked from the API as well:

# Create an invite
curl -X POST http://YOUR_SERVER:32400/api/invites \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"label": "For Alice"}'

# List active invites
curl http://YOUR_SERVER:32400/api/invites \
  -H "Authorization: Bearer ADMIN_TOKEN"

# Revoke an unused invite
curl -X DELETE http://YOUR_SERVER:32400/api/invites/INVITE_ID \
  -H "Authorization: Bearer ADMIN_TOKEN"
Invite info: Before accepting, the invite page shows basic server info. Fetch it publicly with GET /api/invite-info/:token.

Cloud sign-in

When your server is linked to h3xed.app, people sign in with their h3xed.app account and reach your server through the secure relay — no need to expose it directly or hand out a local password. On a LAN-only server, you create local accounts with passwords instead.

Library access

Each account sees only the libraries you've shared with it — choose them when you create the invite, or adjust them later per account from the admin panel. Admin accounts always see everything and can manage the server.

Profiles

Within a single account, set up profiles so everyone sharing that login gets their own space — separate Continue Watching, watchlist, and watch history. Add a profile from the picker, give it a name and avatar, and optionally set a PIN so switching into it requires the code.

# List profiles on the account
curl http://YOUR_SERVER:32400/api/profiles \
  -H "Authorization: Bearer USER_TOKEN"

# Create a profile (optionally managed, with a PIN)
curl -X POST http://YOUR_SERVER:32400/api/profiles \
  -H "Authorization: Bearer USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Kids", "isManaged": true, "pin": "1234"}'

# Switch the active profile
curl -X POST http://YOUR_SERVER:32400/api/profiles/PROFILE_ID/switch \
  -H "Authorization: Bearer USER_TOKEN"

Managed (kids) profiles

Mark a profile as managed to turn it into a kids profile with content restrictions. A managed profile can be limited by:

Restrictions are enforced on every read, and they fail closed — unrated items stay hidden under a rating rule unless you explicitly allow them. Manage them from the admin panel, or via the API:

# Get a profile's restrictions
curl http://YOUR_SERVER:32400/api/users/PROFILE_ID/restrictions \
  -H "Authorization: Bearer ADMIN_TOKEN"

# Set a PG-13 ceiling, deny an "adult" label, allow unrated off
curl -X PUT http://YOUR_SERVER:32400/api/users/PROFILE_ID/restrictions \
  -H "Authorization: Bearer ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "ratingCeilings": ["PG-13"],
    "excludedLabels": ["adult"],
    "allowUnrated": false
  }'

Restrictions also support explicit allowedRatings / excludedRatings and an allowedLabels allow-list if you want finer control than a single ceiling. A managed profile holding its own PIN can't escape into the unrestricted parent profile.

Friends

Friends connect accounts across servers. Send a friend request, accept incoming ones, and see which friends are around with presence. You can block an account to cut off requests and visibility. Friends are who you invite into a watch party, and who you can link servers with for co-op.

Watch party

A watch party plays the same title in sync for everyone in the room. Host one from the web app or Apple TV, then either invite friends directly or share the room's 6-character code so anyone can join from their own device. Playback — play, pause, and seek — stays in step across the room.

Co-op servers

Co-op links your server with a friend's so their libraries appear merged into your app, right alongside your own. Each owner still governs their own content — you set what you share, they set what they share, and managed-profile restrictions still apply to merged content. Duplicate titles across the two servers are de-duplicated so the merged view stays clean.

Watch progress

Watch progress is per profile. The client reports playback position as you watch, and the server keeps a per-profile Continue Watching list:

POST /api/progress
{ "ratingKey": "file-rating-key", "offset": 120000 }

GET /api/continue-watching

Removing access

Remove an account, delete a profile, or revoke an invite from the admin panel. Deleting a profile or account also removes its watch state.

# Delete an account or profile by id
curl -X DELETE http://YOUR_SERVER:32400/api/users/USER_ID \
  -H "Authorization: Bearer ADMIN_TOKEN"
Note: The primary admin (user id 1) can't be deleted.