Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document Group API #198

Open
Foorack opened this issue Dec 1, 2022 · 10 comments
Open

Document Group API #198

Foorack opened this issue Dec 1, 2022 · 10 comments
Assignees
Labels
Priority: Low Low priority, this has least priority to be fixed Type: Enhancement This will **improve** existing or **add** something new

Comments

@Foorack
Copy link
Member

Foorack commented Dec 1, 2022

Written by @ariesclark and @Miner28. Moving to an Issue to better track information across PR's.

Group API

Research Stage

List User Groups GET /users/<user-id>/groups

Response (example)

[
  {
    "id": "gmem_<uuid>",
    "groupId": "grp_<uuid>",
    "memberVisibility": "visible",
    "mutualGroup": true,
    "name": "...",
    "shortCode": "...",
    "discriminator": "0000",
    "description": "...",
    "iconUrl": "https://api.vrchat.cloud/api/1/file/file_<uuid>/1/file",
    "bannerUrl": "https://assets.vrchat.com/www/groups/default_banner.png",
    "privacy": "default",
    "ownerId": "usr_<uuid>",
    "memberCount": 1
  }
]

Create Group POST /groups

Body (example)

{
  "name": "...",
  "shortCode": "...",
  "description": "",
  "joinState": "open",
  "privacy": "default",
  "roleTemplate": "managedFree",
  "bannerId": null,
  "iconId": null
}

name must be at least 3 characters.
shortCode must be at least 3 characters.
joinState one of closed, invite, request, open.
privacy one of default, private.
roleTemplate one of default, managedFree, managedInvite, managedRequest.

Response

Group Object


Get Group GET groups/<group-id>

Query parameters

includeRoles optional boolean, default false.

Response (example)

{
  "id": "grp_<uuid>",
  "name": "...",
  "shortCode": "...",
  "discriminator": "0000",
  "description": "My exciting new group. It's pretty nifty!",
  "iconUrl": "https://assets.vrchat.com/www/groups/default_icon.png",
  "bannerUrl": "https://assets.vrchat.com/www/groups/default_banner.png",
  "privacy": "default",
  "ownerId": "<user-id>",
  "links": [],
  "languages": [],
  "iconId": null,
  "bannerId": null,
  "memberCount": 1,
  "memberCountSyncedAt": "2022-12-01T01:50:50.918Z",
  "isVerified": false,
  "joinState": "open",
  "tags": [],
  "galleries": [],
  "createdAt": "2022-12-01T01:50:50.918Z",
  "initialRoleIds": [
    "grol_<uuid>"
  ],
  "updatedAt": "2022-12-01T01:50:50.918Z",
  "membershipStatus": "member",
  "myMember": {
    "id": "gmem_<uuid>",
    "groupId": "grp_<uuid>",
    "userId": "usr_<uuid>",
    "isRepresenting": false,
    "roleIds": [
      "grol_<uuid>"
    ],
    "joinedAt": "2022-12-01T01:50:50.918Z",
    "membershipStatus": "member",
    "visibility": "visible",
    "isSubscribedToAnnouncements": true,
    "createdAt": "2022-12-01T01:50:50.918Z",
    "managerNotes": "",
    "has2FA": false,
    "permissions": [
      "*"
    ]
  }
}

Update Group PUT groups/<group-id>

Body

{
  "name": "...",
  "shortCode": "...",
  "description": "...",
  "joinState": "open",
  "language": [],
  "links": [],
  "rules": null
}

Response

Group Object


Delete Group DELETE groups/<group-id>

Response

{
  "success": {
    "message": "Group deleted!",
    "status_code": 200
  }
}

List Group Galleries GET /groups/<group-id>/galleries/<group-gallery-id>

Query parameters

looks like the website sends a duplicate parameter galleryId
typical pagination: n, offset.

Response (example)

[
  {
    "id": "ggim_<uuid>",
    "groupId": "grp_<uuid>",
    "galleryId": "ggal_<uuid>",
    "fileId": "file_<uuid>",
    "imageUrl": "https://api.vrchat.cloud/api/1/file/file_<uuid>/1/file",
    "createdAt": "2022-12-01T09:02:57.166Z",
    "submittedByUserId": "usr_<uuid>",
    "approved": true,
    "approvedByUserId": "usr_<uuid>",
    "approvedAt": "2022-12-01T09:02:57.166Z"
  }
]

List Group Roles GET /groups/<group-id>/roles

Response (example)

[
  {
    "id": "grol_<uuid>",
    "groupId": "grp_<uuid>",
    "name": "Group Owner",
    "description": "The owner of this group.",
    "isSelfAssignable": false,
    "permissions": [
      "*"
    ],
    "isManagementRole": true,
    "requiresTwoFactor": false,
    "requiresPurchase": false,
    "order": 0,
    "createdAt": "2022-12-01T09:55:53.794Z",
    "updatedAt": "2022-12-01T09:55:53.794Z"
  }
]

Create Group Role POST /groups/<group-id>/roles

Body (example)

{
  "id": "...",
  "name": "...",
  "description": "",
  "isSelfAssignable": true,
  "permissions": []
}

Response

Group Role Object


Update Group Role PUT /groups/<group-id>/roles/<group-role-id>

Body

assuming same properties as creation.

Response

Array of existing role objects.


Delete Group Role DELETE /groups/<group-id>/roles/<group-role-id>

Body (example)

{
  "id": "...",
  "name": "...",
  "description": "",
  "isSelfAssignable": true,
  "permissions": []
}

Response

Array of existing role objects.


List Group Invites GET /groups/<group-id>/invites

Query parameters

typical pagination: n, offset.

Response (example)

[
  {
    "id": "gmem_<uuid>",
    "groupId": "grp_<uuid>",
    "userId": "usr_<uuid>",
    "isRepresenting": false,
    "user": {
      "id": "usr_<uuid>",
      "displayName": "...",
      "thumbnailUrl": "https://api.vrchat.cloud/api/1/file/file_<uuid>/1/file",
      "iconUrl": ""
    },
    "roleIds": [],
    "joinedAt": null,
    "membershipStatus": "invited",
    "visibility": "visible",
    "isSubscribedToAnnouncements": true,
    "createdAt": "2022-12-01T09:45:00.813Z",
    "bannedAt": null,
    "managerNotes": ""
  }
]

Create Group Invite POST /groups/<group-id>/invites

Body (example)

{
  "userId": "usr_<uuid>",
  "confirmOverrideBlock": true
}

Delete Group Invite DELETE /groups/<group-id>/invites/<user-id>

Response

{
  "success": {
    "message": "... has been uninvited.",
    "status_code": 200
  }
}

List Group Requests GET /groups/<group-id>/requests

Query parameters

typical pagination: n, offset.


List Group Members GET /groups/<group-id>/members

Query parameters

typical pagination: n, offset.

Response (example)

[
  {
    "id": "gmem_<uuid>",
    "groupId": "grp_<uuid>",
    "userId": "usr_<uuid>"
    "isRepresenting": false,
    "user": {
      "id": "usr_<uuid>",
      "displayName": "...",
      "thumbnailUrl": "https://api.vrchat.cloud/api/1/image/file_<uuid>",
      "iconUrl": "https://api.vrchat.cloud/api/1/file/file_<uuid>/1"
    },
    "roleIds": [
      "grol_<uuid>",
    ]
  }
]

List Group Audit Log GET /groups/<group-id>/auditLogs

Query parameters

typical pagination: n, offset.

Response (example)

{
  "results": [
    {
      "id": "gaud_<uuid>",
      "created_at": "2022-12-01T09:31:16.297Z",
      "groupId": "grp_<uuid>",
      "actorId": "usr_<uuid>",
      "actorDisplayName": "...",
      "targetId": "grp_<uuid>",
      "eventType": "group.create",
      "description": "Group test created by <displayName>.",
      "data": {
        "name": "...",
        "shortCode": "...",
        "description": "...",
        "rules": null,
        "bannerId": null,
        "iconId": "file_<uuid>",
        "joinState": "open",
        "privacy": "default",
        "ownerId": "usr_<uuid>",
        "iconVersion": 1,
        "galleries": [
          {
            "_id": "ggal_<uuid>",
            "_created_at": "2022-12-01T09:31:16.297Z",
            "_updated_at": "2022-12-01T09:31:16.297Z",
            "name": "Banner and Icon",
            "description": "A gallery to store your group's banner and icon. You can edit this any way you like later.",
            "membersOnly": true
          }
        ]
      }
    }
  ],
  "totalCount": 1,
  "hasNext": false
}

List Group Permissions GET /groups/<group-id>/permissions

Response (example)

[
  {
    "name": "group-members-manage",
    "displayName": "Manage Group Member Data",
    "help": "Allows role to view all members and edit data about them.",
    "isManagementPermission": true,
    "allowedToAdd": true
  }
]

Get Group Announcement GET /groups/<group-id>/announcement

Response (example)

Empty object when no announcement or

{
  "id": "gpos_<uuid>",
  "groupId": "grp_<uuid>",
  "authorId": "usr_<uuid>",
  "title": "a",
  "text": "a",
  "imageId": null,
  "imageUrl": null,
  "createdAt": "2022-12-01T09:12:48.487Z",
  "updatedAt": "2022-12-01T09:12:48.487Z"
}

Set Group Announcement POST /groups/<group-id>/announcement

Body

{
  "text": "...",
  "title": "...",
  "imageId": null,
  "sendNotification": false
}

Response

Group Announcement Object


List Group Instances GET /groups/<group-id>/instances


Delete Join Request DELETE /groups/<group-id>/requests


Create Join Request POST /groups/<group-id>/join


List Group Role Templates GET /groups/roleTemplates


Feedback API? /users/<user-id>/feedback?contentId=<group-id>&metadata=true


POST /feedbacks/group/<group-id>

{
   "type":"report",
   "reasons":[
      "inappropriate",
      "abusive_disruptive",
      "malicious",
      "hateful"
   ],
   "locations":[
      "group_name",
      "group_description",
      "image_banner_gallery_icon",
      "group_user_behaviour"
   ],
   "description":"a"
}

RESPONSE

{
   "id":"feedback_<uuid>",
   "type":"report",
   "reasons":[
      "inappropriate",
      "abusive_disruptive",
      "malicious",
      "hateful"
   ],
   "locations":[
      "group_name",
      "group_description",
      "image_banner_gallery_icon",
      "group_user_behaviour"
   ],
   "description":"Report comment",
   "commenterId":"usr_<uuid>",
   "commenterName":"<displayname>",
   "contentId":"grp_<uuid>",
   "contentType":"group",
   "contentName":"test",
   "tags":[
      
   ]
}

PUT /groups/<groupId>/requests/<userId>

{
  "action":"accept" | "reject"
}

ACCEPT RESPONSE

{
    "success": {
        "message": "Successfully accepted <display-name> request.",
        "status_code": 200
    }
}

REJECT RESPONSE

{
    "success": {
        "message": "Successfully rejected <display-name> request.",
        "status_code": 200
    }
}
@Foorack Foorack added Type: Enhancement This will **improve** existing or **add** something new Priority: High High priority, this ideally needs to be fixed first Status: In Progress This is being worked on... labels Dec 1, 2022
@Foorack Foorack mentioned this issue Dec 1, 2022
@Foorack
Copy link
Member Author

Foorack commented Dec 1, 2022

Name and shortcode follow standard sanitation functions:

{
	"error": {
		"message": "name did not pass sanitization‚ shortCode did not pass sanitization",
		"status_code": 400
	}
}

@Miner28
Copy link
Collaborator

Miner28 commented Dec 1, 2022

/groups/<group-id>/galleries

{name: "E1", description: "E2", membersOnly: false}

name - required

@Foorack Foorack added Priority: Low Low priority, this has least priority to be fixed and removed Priority: High High priority, this ideally needs to be fixed first Status: In Progress This is being worked on... labels Dec 4, 2022
@Foorack
Copy link
Member Author

Foorack commented Dec 4, 2022

Keeping this open as groups/<groupId>/instances is missing, but that is broken.

@Foorack
Copy link
Member Author

Foorack commented Dec 4, 2022

And /groups/strictsearch?query=abc

@Foorack
Copy link
Member Author

Foorack commented Dec 4, 2022

@Protected
Copy link

Protected commented Mar 4, 2023

All GroupMember examples in the documentation have "membershipStatus": "member". The GroupMember examples displayed for the respective endpoints should be updated to display:

  • When in response to a join request or representing a user who requested to join, but whose request hasn't yet been approved: "membershipStatus": "requested".
  • When in response to requesting the list of invited members who haven't yet accepted their invites ("Sent" in the website): "membershipStatus": "invited"
  • When the user is banned (in addition to the ban date): "membershipStatus": "banned"

(all of these have been tested.)

@JessyCat92
Copy link

JessyCat92 commented Mar 31, 2024

Maybe one more thing: They changed recently that you can create multiple announcements, so Endpoint /groups/{groupId}/announcement is not used by VRC anymore (at least on website) instead they have new Posts Apis:

Read Posts

GET /groups/{groupId}/posts?n=10&offset=0&publicOnly=false
Reponse looks like:

{
    "total": 2,
    "posts": [
        {
            "id": "not_163d458f-f9a5-4ff8-9ce7-5879777997b4",
            "groupId": "grp_03c380ba-812a-4b3a-ae65-f0da222fc103",
            "authorId": "usr_362cdd9f-3b2d-4ff5-afa7-65a2d3f8435d",
            "editorId": null,
            "visibility": "public",
            "roleIds": [],
            "title": "asd",
            "text": "asd",
            "imageId": null,
            "imageUrl": null,
            "createdAt": "2024-03-31T14:07:53.188Z",
            "updatedAt": "2024-03-31T14:07:53.188Z"
        },
        {
            "id": "not_ec21137e-2271-4e8a-8216-f0a008033f1d",
            "groupId": "grp_03c380ba-812a-4b3a-ae65-f0da222fc103",
            "authorId": "usr_362cdd9f-3b2d-4ff5-afa7-65a2d3f8435d",
            "editorId": null,
            "visibility": "group",
            "roleIds": [],
            "title": "test",
            "text": "test please ignore",
            "imageId": null,
            "imageUrl": null,
            "createdAt": "2024-03-31T14:07:37.504Z",
            "updatedAt": "2024-03-31T14:07:37.504Z"
        }
    ]
}

To Create a new Post:

POST /groups/{groupId}/posts
Body:

{
    "text":"test",
    "title":"Yeah I am sry need one more test",
    "imageId":null,
    "sendNotification":true,
    "roleIds":["grol_a1be5571-4a46-42c7-ae84-7a1e1262ee68","grol_e1ec0583-a87b-4b46-a0e0-86b4dfc1361b"],
    "visibility":"group"
}

Response:

{
    "id": "not_a9f5f5d8-c1c7-4d1c-a228-f1b6140d29b5",
    "groupId": "grp_03c380ba-812a-4b3a-ae65-f0da222fc103",
    "authorId": "usr_362cdd9f-3b2d-4ff5-afa7-65a2d3f8435d",
    "editorId": null,
    "visibility": "group",
    "roleIds": [
        "grol_a1be5571-4a46-42c7-ae84-7a1e1262ee68",
        "grol_e1ec0583-a87b-4b46-a0e0-86b4dfc1361b"
    ],
    "title": "Yeah I am sry need one more test",
    "text": "test",
    "imageId": null,
    "imageUrl": null,
    "createdAt": "2024-03-31T14:11:41.923Z",
    "updatedAt": "2024-03-31T14:11:41.923Z"
}

Delete Post

DELETE /groups/{groupId}/posts/not_a9f5f5d8-c1c7-4d1c-a228-f1b6140d29b5

Reponse:

{
    "success": {
         "message":"Group post was deleted!",
         "status_code":200
     }
}

Fields:

  • visibility can be "public" or "group" - can be filtered on get request with publicOnly=true
  • roleIds can contain Ids only if visibility is "group" - therefore post is only shown inside group to defined roles
  • don't know what editorId is on Reponses....

@jellejurre
Copy link
Contributor

Note: only GET /groups/roleTemplates and /users//feedback?contentId=&metadata=true seem to be missing

@VinyarionHyarmendacil
Copy link
Contributor

Note: only GET /groups/roleTemplates and /users//feedback?contentId=&metadata=true seem to be missing

/users/{userId}/feedback is addressed in #413

@jellejurre
Copy link
Contributor

Oh, true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Priority: Low Low priority, this has least priority to be fixed Type: Enhancement This will **improve** existing or **add** something new
Development

No branches or pull requests

7 participants