Skip to content

API Reference

RacoonByte01 edited this page Oct 7, 2026 · 1 revision

API Reference

Base URL: http://localhost:8080

  • Parameters marked Yes are required; No means optional (default noted).
  • Parameters are sent as multipart form fields (curl -F), never in the query string — secrets stay out of URLs, access logs and proxies. On the wire they are still plaintext until HTTPS is enabled.
  • Authorization is a request header whose value is the raw token returned by /login — no Bearer prefix.
  • -F 'name=value' for direct values, -F 'field=<-' to stream a file or pipe (gpg output) into a field.

Quick flow

TOKEN=$(curl -s -F 'name=alice' -F 'password=secret' "http://localhost:8080/login")
curl -s -H "Authorization: $TOKEN" "http://localhost:8080/groups"

Users

GET /users

Returns all users. Serialized with the Public view: only name and pgp (no password hash, no tokens).

curl "http://localhost:8080/users"

Response: [{"name":"alice","pgp":null}]

GET /user/{name}

Returns one user (public view) or null if the name does not exist.

Parameter In Required
name path Yes
curl "http://localhost:8080/user/alice"

POST /user

Creates a new user. The password is stored as SHA-512.

Parameter In Required
name form Yes
password form Yes
curl -F 'name=alice' -F 'password=secret' "http://localhost:8080/user"
  • If the name is already in use, the response body is null and nothing is created.

PUT /user

Updates the authenticated user (name, password and/or PGP key). Nothing is cleared unless you ask for it.

Parameter In Required Default
Authorization header Yes —
name form No unchanged
password form No unchanged
pgp form No unchanged
pgp_null form No false (set true to delete the stored PGP key)
# change the password
curl -X PUT -H "Authorization: $TOKEN" -F 'password=newsecret' "http://localhost:8080/user"

# export the PGP public key from the keyring and pipe it into the field
gpg --export --armor <id-pgp> \
  | curl -X PUT -H "Authorization: $TOKEN" -F 'pgp=<-' "http://localhost:8080/user"

# remove the PGP key
curl -X PUT -H "Authorization: $TOKEN" -F 'pgp_null=true' "http://localhost:8080/user"

DELETE /user

Deletes the authenticated user.

Parameter In Required
Authorization header Yes
curl -X DELETE -H "Authorization: $TOKEN" "http://localhost:8080/user"

Warning

The user's entries in group userRole maps are not cleaned up; groups keep a stale name reference.


Tokens

GET /tokens

Returns all tokens of the authenticated user (sessions).

Parameter In Required
Authorization header Yes
curl -H "Authorization: $TOKEN" "http://localhost:8080/tokens"

POST /login

Exchanges name + password for a token (32 random bytes, Base64url).

Parameter In Required
name form Yes
password form Yes
curl -F 'name=alice' -F 'password=secret' "http://localhost:8080/login"
# → NnQ8v... (raw token string)
  • Unknown user → 404 Not Found.
  • Wrong password → returns the string a instead of an error (see Home#Known limitations).
  • The password is not PGP-encrypted: the server verifies it as the SHA-512 hash of the plaintext, so it cannot decrypt it. HTTPS is what protects it on the wire.

DELETE /token

Deletes one of your tokens. The user is resolved through the token form field.

Parameter In Required
Authorization header Yes
token form Yes (the token to revoke)
curl -X DELETE -H "Authorization: $TOKEN" \
  -F 'token=OTHER_TOKEN' "http://localhost:8080/token"

DELETE /logout

Deletes the token used in the Authorization header (ends that session).

Parameter In Required
Authorization header Yes
curl -X DELETE -H "Authorization: $TOKEN" "http://localhost:8080/logout"

Groups

Role = the caller's bit mask inside that group — see Roles.

GET /groups

Returns every group the authenticated user belongs to.

Parameter In Required
Authorization header Yes
curl -H "Authorization: $TOKEN" "http://localhost:8080/groups"

Response: [{"id":0,"name":"team"}] (userRole map is also included).

GET /group/{id}

Returns the group if the caller is a member, otherwise null.

Parameter In Required
id path Yes
Authorization header Yes
curl -H "Authorization: $TOKEN" "http://localhost:8080/group/0"

POST /group

Creates a group. The creator is stored with role 127 (full control).

Parameter In Required
name form Yes
Authorization header Yes
curl -F 'name=team' -H "Authorization: $TOKEN" "http://localhost:8080/group"

Response includes the assigned id (first group is 0).

POST /group/{id} — add user

Adds an existing user to the group. Requires bit 2 (add user).

Parameter In Required Default
id path Yes —
name form Yes (user to add) —
roles form No 3 (read + write)
Authorization header Yes —
# add bob with default role 3
curl -H "Authorization: $TOKEN" -F 'name=bob' "http://localhost:8080/group/0"

# add bob as moderator (read+write+add+delete user = 1+2+4+16 = 23)
curl -H "Authorization: $TOKEN" -F 'name=bob' -F 'roles=23' "http://localhost:8080/group/0"
  • Unknown target user or missing permission → null body, nothing changes.

PUT /group/{id} — rename group

Requires bit 5 (update group).

Parameter In Required
id path Yes
name form Yes (new group name)
Authorization header Yes
curl -X PUT -H "Authorization: $TOKEN" \
  -F 'name=new-team-name' "http://localhost:8080/group/0"

PUT /group/{id}/{name} — set a user's role

Overwrites the role of the member {name}. Requires bit 3 (update roles) on the caller; both users must be in the group.

Parameter In Required
id path Yes
name path Yes (member whose role changes)
roles form Yes (Byte, 0–127)
Authorization header Yes
# promote bob to 127 (admin)
curl -X PUT -H "Authorization: $TOKEN" \
  -F 'roles=127' "http://localhost:8080/group/0/bob"

DELETE /group/{id} — delete group

Requires bit 6 (delete group).

Parameter In Required
id path Yes
Authorization header Yes
curl -X DELETE -H "Authorization: $TOKEN" "http://localhost:8080/group/0"

Note

The group's message file data/groups/<id>.json is not deleted.

DELETE /exit/{id} — leave group

Removes the caller from the group. Membership only, no bit needed.

Parameter In Required
id path Yes
Authorization header Yes
curl -X DELETE -H "Authorization: $TOKEN" "http://localhost:8080/exit/0"
  • The last member (typically role 127) can leave, orphaning the group.

DELETE /group/{id}/{name} — remove a member

Removes {name} from the group. Requires bit 4 (delete user).

Parameter In Required
id path Yes
name path Yes (member to remove)
Authorization header Yes
curl -X DELETE -H "Authorization: $TOKEN" "http://localhost:8080/group/0/bob"

Messages

Messages live in data/groups/<id>.json. The server never encrypts — you encrypt client-side with GnuPG and the server stores only the armored ciphertext.

GET /messages/{id}

Returns all messages of the group. Requires bit 0 (read).

Parameter In Required
id path Yes
Authorization header Yes
curl -H "Authorization: $TOKEN" "http://localhost:8080/messages/0"

Response: [{"content":"-----BEGIN PGP MESSAGE-----...","date_post":"2026-10-07T12:00:00"}]

POST /send/{id} — send a message

Appends a message. Requires bit 1 (write). The content must contain one of:

  • -----BEGIN PGP PUBLIC KEY BLOCK-----
  • -----BEGIN PGP PRIVATE KEY BLOCK-----
  • -----BEGIN PGP MESSAGE-----
  • -----END PGP MESSAGE-----
Parameter In Required
id path Yes
message form Yes
Authorization header Yes

Encrypt to the recipient's public key and stream the ciphertext straight into the form field:

gpg --encrypt --armor --recipient <id-pgp> message.txt \
  | curl -H "Authorization: $TOKEN" -F 'message=<-' "http://localhost:8080/send/0"

Short flags — gpg -ear <id-pgp>:

gpg -ear <id-pgp> message.txt \
  | curl -H "Authorization: $TOKEN" -F 'message=<-' "http://localhost:8080/send/0"
  • Encrypt once per recipient key for private conversations, or to a shared group key.
  • Content without a PGP marker is silently discarded (HTTP 200, nothing stored).
  • Response body is empty on success.

Status codes

Code When
200 Success (also returned with a null body when a permission check fails or an entity is missing)
400 Missing required parameter
404 /login with unknown user

Important

Permission failures do not return 403 — the endpoints respond with an empty/null body. Treat null as "not allowed or not found".