Skip to content

Commit 6610e55

Browse files
authored
Merge pull request #13 from VinyarionHyarmendacil/shortlinks-wserr-2
Expand shortlinks and instances, add error messages to websocket
2 parents cd4a252 + a8ecb77 commit 6610e55

3 files changed

Lines changed: 141 additions & 67 deletions

File tree

content/docs/(guides)/instances.mdx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
---
22
title: Instances
33
icon: Boxes
4+
description: Instances are parallel "rooms" or "lobbies" of a world. Each instance can only hold a limited number of users, but there is no limit on how many instances can exist of a world. Instances are uniquely identified by the combined World ID and Instance ID.
45
---
56

6-
Instances are parallel "rooms" or "lobbies" of a world.
7-
Each instance can only hold a limited number of users, but there is no limit on how many instances can exist of a world.
8-
Instances are uniquely identified by the combined World ID and Instance ID.
9-
107
<Callout>
118
As of 2024-05-02, VRChat indicated in [a Developer
129
Update](https://ask.vrchat.com/t/developer-update-2-may-2024/24284#changes-to-instance-apis-and-auto-creation-13)
@@ -18,28 +15,48 @@ Instances are uniquely identified by the combined World ID and Instance ID.
1815
## Instance ID
1916

2017
The instance ID is the combined sum of all the arguments to the instance e.g. name, owner, and privacy setting.
21-
The arguments are in the order of name, friends, hidden, private, canRequestInvite, region, nonce.
18+
The arguments are formatted in the order: `name`, one of: (`friends` | hidden` | `private` | (`group`, `groupAccessType`)), `ageGate`, `canRequestInvite`, `region`, `nonce`.
2219

2320
### Owner ID
2421

2522
Differentiate two concepts, "Instance Owner" and "Instance Master".
2623
The "Owner" of an instance is the creator of the instance, is permanent, and has permission to insta-kick users without having to go through the Voting system.
2724
The "Instance Master" is the Photon sync master and is responsible for object syncing. The Instance Master is whoever has stayed in the instance the longest.
2825

29-
### Nonce
26+
The presence of one of the arguments `friends`, `hidden`, `private`, or `group` indicates that the instance has a canonical owner.
27+
The `group` argument indicates that an instance is a group instance.
28+
29+
In particular:
30+
31+
| Instance Type | InstanceID fragment |
32+
| ------------- | -------------------------------------------- |
33+
| Public | (n/a) |
34+
| Friends Plus | `~hidden(<userId>)` |
35+
| Friends | `~friends(<userId>)` |
36+
| Invite Plus | `~private(<userId>)~canRequestInvite` |
37+
| Invite | `~private(<userId>)` |
38+
| Group Public | `~group(<groupId>)~groupAccessType(public)` |
39+
| Group Plus | `~group(<groupId>)~groupAccessType(plus)` |
40+
| Group Members | `~group(<groupId>)~groupAccessType(members)` |
3041

31-
Nonce is the Cryptographic key used to lock non-public instances to prevent people from guessing the Instance ID. It is not included in the location of public instances, and is formatted as "nonce(key)" where key is the cryptographic key.
42+
### Age Gate
43+
44+
`~ageGate` indicates that only users who are 18+ verified can join the instance. Users do not necessarily need to actively display 18+ verification on their profiles.
3245

3346
### Region
3447

35-
Region indicates the geographical location of the Photon servers used for the instance. **Default:** `us`
48+
`~region(<token>)` indicates the geographical location of the Photon servers used for the instance. **Default:** `us`
3649

3750
| Region | Hosted in | Token |
3851
| --------- | --------------- | ----- |
39-
| USA, West | San José | us |
40-
| USA, East | Washington D.C. | use |
41-
| Europe | Amsterdam | eu |
42-
| Japan | Tokyo | jp |
52+
| USA, West | San José | `us` |
53+
| USA, East | Washington D.C. | `use` |
54+
| Europe | Amsterdam | `eu` |
55+
| Japan | Tokyo | `jp` |
56+
57+
### Nonce
58+
59+
`~nonce(<value>)` is the Cryptographic key used to lock non-public instances to prevent people from guessing the Instance ID. It is not included in the location of public instances, and is formatted as "nonce(key)" where key is the cryptographic key.
4360

4461
### Special Values
4562

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,71 @@
11
---
22
title: Short Links
33
icon: Files
4+
description: VRChat has a number of ways to shorten URLs for users, instances, groups, and calendar events. These redirect people to the `https://vrchat.com/home/...` pages on the website.
45
---
56

6-
VRChat has several ways users can share links to instances, users, and groups.
7+
VRChat has several ways users can share links to various types of content.
78
Canonically, the URLs that many people will use are those they see in their browser, starting with `https://vrchat.com/home/...`.
8-
But there are other URLs for users, groups, worlds, and instances that offer brevity.
9-
Each of the following describes an HTTP `GET` request, where VRChat replies with an HTTP `302 Found` and the target URL in the `Location` header of the response.
9+
However, there are other URLs for users, groups, worlds, instances, and calendar events that offer brevity.
1010

11-
### Users
11+
## HTTP Redirects
1212

13-
`https://vrch.at/<userId>` redirects to `https://vrchat.com/home/user/<userId>`
13+
<Callout type="info">
14+
Upon receiving a `GET` request, VRChat will sometimes chain redirects, replying with `302 Found`, `302 Moved Temporarily`, or `307 Temporary Redirect` with a target url in the `Location` response header.
15+
If the HTTP `GET` was directed at an api endpoint (URL paths starting with `/api/1/`), you will need to sumbit a properly formatted `User-Agent` header with the request.
16+
For example, the `GET https://vrc.group/VRCHAT.0000` redirect looks like this:
1417

15-
### Worlds
18+
```properties
19+
GET /VRCHAT.0000 HTTP/1.1
20+
Host: vrc.group
21+
User-Agent: example/4.2.67 example@vrchat.community; https://discord.gg/vrchat; https://github.com/vrchatapi/vrchat.community
22+
Accept: */*
23+
24+
HTTP/1.1 302 Found
25+
Date: Mon, 06 Apr 2026 21:52:45 GMT
26+
Content-Length: 0
27+
Connection: keep-alive
28+
Location: https://vrchat.com/api/1/groups/redirect/VRCHAT.0000
29+
```
30+
31+
</Callout>
1632

17-
`https://vrch.at/<worldId>` redirects to `https://vrchat.com/home/world/<worldId>`
33+
### Users
34+
35+
`https://vrch.at/<userId>`
36+
- redirects to `https://vrchat.com/home/user/<userId>`
37+
38+
Notably, this method does not work for users with old IDs like `8JoV9XEdpo` (the UserID for the official VRChat account), as these are interpreted as `shortName`s for instances.
1839

1940
### Instances
2041

21-
`https://vrch.at/<shortName>` redirects to `https://vrchat.com/i/<shortName>`
22-
`https://vrchat.com/i/<shortName>` redirects to `https://vrchat.com/home/launch?worldId=<worldId>&instanceId=<instanceId>&shortName=<shortName>`
42+
`https://vrch.at/<shortName>`
43+
- redirects to `https://vrchat.com/i/<shortName>`
44+
- which redirects to `https://vrchat.com/home/launch?worldId=<worldId>&instanceId=<instanceId>&shortName=<shortName>`
45+
46+
### Worlds
47+
48+
Worlds are treated as a special case for instances. They do not link directly to the world info page.
49+
50+
`https://vrch.at/<worldId>`
51+
- redirects to `https://vrchat.com/home/launch?worldId=<worldId>`
2352

2453
### Groups
2554

26-
`https://vrc.group/<groupCodeAndDisc>` redirects to `https://vrchat.com/api/1/groups/redirect/<groupCodeAndDisc>`
27-
`https://vrchat.com/api/1/groups/redirect/<groupCodeAndDisc>` redirects to `https://vrchat.com/home/group/<groupId>`
28-
This last one is actually programmatically useful, as it can be used to resolve a group code with discriminator to the group's ID without having to use the 'search groups' API endpoint.
29-
Ex.: `GET https://vrchat.com/api/1/groups/redirect/VRCHAT.0000` redirects to `https://vrchat.com/home/group/grp_7ccb6ca3-cd36-4dab-9ab1-7bcf08d794e4`
55+
`https://vrc.group/<groupCodeAndDisc>`
56+
- redirects to `https://vrchat.com/api/1/groups/redirect/<groupCodeAndDisc>`
57+
- which redirects to `https://api.vrchat.com/api/1/groups/redirect/<groupCodeAndDisc>`
58+
- which redirects to `https://vrchat.com/home/group/<groupId>`
59+
60+
The last redirect is actually programmatically useful, as it can be used to resolve a group code with discriminator to the group's ID without having to use the 'search groups' API endpoint.
61+
Ex.: `GET https://api.vrchat.com/api/1/groups/redirect/VRCHAT.0000` redirects to `https://vrchat.com/home/group/grp_7ccb6ca3-cd36-4dab-9ab1-7bcf08d794e4`
62+
63+
### Calendar Events
64+
65+
`https://vrch.at/c/<shortCode>`
66+
- redirects to `https://vrchat.com/api/1/shortCode/c/<shortCode>`
67+
- which redirects to `https://vrchat.com/home/group/<groupId>/calendar/<calendarId>`
68+
69+
<Callout>
70+
As of 2026-04-06, the last redirect is speculative (as `/api/1/shortCode/c/<shortCode>` always returns a `404 Not Found`), but is based on unused code visible in the website.
71+
</Callout>

content/docs/(guides)/websocket.mdx

Lines changed: 57 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: VRChat's Websocket API, also known as "the pipeline", is used recei
66

77
## Connecting
88

9-
Connecting to the VRChat webhook server is done via the URL:
9+
Connecting to the VRChat websocket server is done via the URL:
1010

1111
```
1212
wss://pipeline.vrchat.cloud/?authToken=authcookie_...
@@ -19,7 +19,7 @@ It is possible to be connected from multiple locations at the same time. All cli
1919
<Callout type="info">
2020
**Most messages are double-encoded!**
2121

22-
All notification `content` values will be documented in JSON object form. The "`content`" frield is a **stringified** version of the JSON object, and needs to be unpacked separately. _(with the exception of `see-notification` and `hide-notification` events, which take a notification ID instead.)_
22+
All notification `content` values will be documented in JSON object form. The "`content`" field is a **stringified** version of the JSON object, and needs to be unpacked separately. _(with the exception of `see-notification` and `hide-notification` events, which take a notification ID instead.)_
2323

2424
```json
2525
{
@@ -30,48 +30,20 @@ All notification `content` values will be documented in JSON object form. The "`
3030

3131
</Callout>
3232

33-
## Note on Enumerations
33+
### Error messages
3434

35-
Several JSON string values present in both Websocket API messages and HTTP API responses appear to be contained in predictably consistent sets.
36-
Throughout both APIs, the empty string `""` is returned in places (including the immediately) where it would seem otherwise reasonable to have a `null` or undefined value.
37-
In this part of the documentation, the following `":identifier"`s will be used to describe possible enumeration-ish values:
35+
In some cases, although a websocket connection may open successfully, it may have or develop an invalid state, in which case an error message is sent to the client and the connection is closed.
3836

39-
- `":locationString"`
40-
- `""` Pseudo-null value
41-
- `"offline"` Implies a user currently is not either running the VRChat client or connected to the Pipeline (e.g., browser tab open)
42-
- `"traveling"` Indicates a user's client is travelling between instances (e.g., downloading world, synchronizing world state)
43-
- Also can be `"traveling:traveling`
44-
- `"private"` Indicates a user's location is not visible to the currently logged-in user. (e.g., Ask Me/Do Not Disturb status, Invite/Invite+/Group instance)
45-
- _other values_ An actual location (see [Instances](/instances))
46-
- `":platformString"`
47-
- `""` Pseudo-null value
48-
- `"standalonewindows"`
49-
- `"android"`
50-
- `"web"` User is on a https://vrchat.com/home page
51-
- _other values_ Some other platform or third-party application (e.g., `"ios"` could be the value for a future build on some Apple devices)
52-
- `":contentRefreshContentTypeEnum"`
53-
- `"gallery"`
54-
- `"icon"`
55-
- `"emoji"`
56-
- `"print"`
57-
- `"prints"` is also a value observed, but this never has an id attached
58-
- `"sticker"`
59-
- `"inventory"` appears to mirror other
60-
- `"avatar"`
61-
- `"world"`
62-
- _other values_ Some other user-uploaded content
63-
- `":contentRefreshActionTypeEnum"`
64-
- `"created"`
65-
- `"deleted"`
66-
- `"add"` \*
67-
- `"delete"` \*
68-
- _other values_ Not expected<br/> \* _only observed with_ `"inventory"` _content type_
69-
- `":inventoryType"`
70-
- `"sticker"`
71-
- `"emoji"`
72-
- `"bundle"`
73-
- `"prop"`
74-
- _other values_ Some other user-uploaded or creator economy content
37+
```json
38+
{
39+
"err": <string>, // A text description of the error
40+
"<additional>": <value> // Additional properties describing the context of the error
41+
}
42+
```
43+
44+
For example:
45+
- VRChat is experiencing a service outage: `{"err":"Error finding user {userId}"}`
46+
- Websocket connection opened from a client IP address different from the one issued the `authToken`: `{"err":"authToken doesn't correspond with an active session","authToken":"{authToken}","ip":"{ipAddress}"}`
7547

7648
## Events
7749

@@ -568,3 +540,46 @@ Role structure matches the GroupRole object from the [Groups API](/reference/get
568540
}
569541
}
570542
```
543+
544+
## Note on Enumerations
545+
546+
Several JSON string values present in both Websocket API messages and HTTP API responses appear to be contained in predictably consistent sets.
547+
Throughout both APIs, the empty string `""` is returned in places where it would otherwise seem reasonable to have a `null` or undefined value.
548+
In this part of the documentation, the following `":identifier"`s will be used to describe possible enumeration-ish values:
549+
550+
- `":locationString"`
551+
- `""` Pseudo-null value
552+
- `"offline"` Implies a user currently is not either running the VRChat client or connected to the Pipeline (e.g., browser tab open)
553+
- `"traveling"` Indicates a user's client is travelling between instances (e.g., downloading world, synchronizing world state)
554+
- Also can be `"traveling:traveling`
555+
- `"private"` Indicates a user's location is not visible to the currently logged-in user. (e.g., Ask Me/Do Not Disturb status, Invite/Invite+/Group instance)
556+
- _other values_ An actual location (see [Instances](/instances))
557+
- `":platformString"`
558+
- `""` Pseudo-null value
559+
- `"standalonewindows"`
560+
- `"android"`
561+
- `"web"` User is on a https://vrchat.com/home page
562+
- _other values_ Some other platform or third-party application (e.g., `"ios"` could be the value for a future build on some Apple devices)
563+
- `":contentRefreshContentTypeEnum"`
564+
- `"gallery"`
565+
- `"icon"`
566+
- `"emoji"`
567+
- `"print"`
568+
- `"prints"` is also a value observed, but this never has an id attached
569+
- `"sticker"`
570+
- `"inventory"` appears to mirror other
571+
- `"avatar"`
572+
- `"world"`
573+
- _other values_ Some other user-uploaded content
574+
- `":contentRefreshActionTypeEnum"`
575+
- `"created"`
576+
- `"deleted"`
577+
- `"add"` \*
578+
- `"delete"` \*
579+
- _other values_ Not expected<br/> \* _only observed with_ `"inventory"` _content type_
580+
- `":inventoryType"`
581+
- `"sticker"`
582+
- `"emoji"`
583+
- `"bundle"`
584+
- `"prop"`
585+
- _other values_ Some other user-uploaded or creator economy content

0 commit comments

Comments
 (0)