Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
f3b9b9a
feat(instances): document calendar event linking
BASIC-BIT Aug 31, 2026
4a2db6e
fix(instances): address calendar link review
BASIC-BIT Sep 3, 2026
1147a46
test(instances): isolate calendar link validation
BASIC-BIT Sep 3, 2026
b883025
test(instances): cover cross-group calendar links
BASIC-BIT Sep 3, 2026
404c2b8
docs(instances): document cross-group calendar links
BASIC-BIT Sep 3, 2026
e2ec741
docs(instances): refine update error responses
BASIC-BIT Sep 3, 2026
b25f54b
test(instances): remove redundant update workflows
BASIC-BIT Sep 3, 2026
41c0153
test(instances): consolidate calendar link coverage
BASIC-BIT Sep 3, 2026
9565a5a
docs(instances): document calendar link permissions
BASIC-BIT Sep 3, 2026
e76f4a8
Feat/profile+user changes (#600)
StarLight-Oliver Sep 16, 2026
2a62f54
fix(users): drop the profile fields the user endpoints no longer return
ariesclark Sep 16, 2026
a573e50
fix(groups): describe the member a foreign group's member list returns
ariesclark Sep 16, 2026
aedfe12
feat(users): document the public profile's theme, banner and public w…
ariesclark Sep 16, 2026
c7027b3
feat(api): document seven routes the spec had never described
ariesclark Sep 16, 2026
ae7e889
fix(users): add the banner and past-name fields the user endpoints re…
ariesclark Sep 16, 2026
1e1b44c
fix(worlds): add isHypeTrainEligible, pendingUpload and a nullable cr…
ariesclark Sep 16, 2026
a11632b
feat(api): document seven more routes and the parameters that reach them
ariesclark Sep 16, 2026
0011c5b
chore(deps): update redocly to 2.53.1
ariesclark Sep 16, 2026
cdfc846
fix(users): type the presence avatar tags as the string traffic carries
ariesclark Sep 16, 2026
855165e
test: drop the CSS and JavaScript workflows
ariesclark Sep 16, 2026
b9948ff
test: report failures as annotations and a step summary
ariesclark Sep 16, 2026
127d86d
fix(test): cap the annotations a failing run emits
ariesclark Sep 16, 2026
ac5f917
test: stop running report.sh in CI
ariesclark Sep 16, 2026
6e8dbcd
test: trace report.sh in CI to find what its jq blocks on
ariesclark Sep 16, 2026
dbc1118
test: upload the respect report so its stall can be reproduced locally
ariesclark Sep 16, 2026
720d47a
docs(test): name the cost the message slice avoids [no release]
ariesclark Sep 16, 2026
f2d457e
chore(ci): let a commit opt out of the release with [no release]
ariesclark Sep 16, 2026
3e8ab3a
test: run report.sh in CI again, under a timeout [no release]
ariesclark Sep 16, 2026
739e68c
fix(config): `economyLedgerBackfill` is no longer present in `getConfig`
ariesclark Sep 16, 2026
aae3e7e
fix(infopush): `command` can be `OpenWorldsMenu` or `scrollToShelf`
ariesclark Sep 16, 2026
689ac1d
fix(infopush): `groupPool`, `worldPool` and `hoverToJoin` are present
ariesclark Sep 16, 2026
e94d5b8
test: report every failure a check names, grouped by workflow [no rel…
ariesclark Sep 16, 2026
d6730d7
fix(economy): listings do not carry `refundable` or `storeIds`
ariesclark Sep 16, 2026
ace8fb4
fix(economy): a store shelf carries four more image ids
ariesclark Sep 16, 2026
28d8d98
fix(economy): `collaborationId` is present on a listing attribution
ariesclark Sep 16, 2026
bdbc1e9
fix(props): `authorId` is not required by `listProps`
ariesclark Sep 16, 2026
c6da0d6
chore: release 1.21.0
ariesclark Sep 16, 2026
e59884d
fix(users): `targetUser.id` on a note holds a user id
ariesclark Sep 16, 2026
d69fe77
refactor(schemas): give the hex color string its own type
ariesclark Sep 16, 2026
31ffa3e
style: normalise the stray CRLF files to LF
ariesclark Sep 16, 2026
9d9c24b
docs: note the traps this release surfaced
ariesclark Sep 16, 2026
2c2c13a
feat(openapi): drop deleted routes from the published bundles
ariesclark Sep 16, 2026
2880311
docs: say what the x-deleted date means and where to find it
ariesclark Sep 16, 2026
33275fa
Add `nameplateId` go UpdateGroupRequest (#602)
lillithrosepup Sep 18, 2026
7567718
refactor(inventory): rename getCosmeticIndex to getCosmetics
ariesclark Sep 16, 2026
287c281
fix(spectral): read a run of capitals as an acronym
ariesclark Sep 16, 2026
2e82d34
docs(schemas): use the American spellings the repo uses elsewhere
ariesclark Sep 16, 2026
97bbb08
docs: record the one object, one file rule
ariesclark Sep 16, 2026
5ba2364
refactor(schemas): extract ConnectedAccountDetails and PlatformHistor…
ariesclark Sep 16, 2026
d7088c3
fix(infopush): an announcement carries title, body, media and deliver…
ariesclark Sep 20, 2026
9cdcf27
fix(friends): `currentAvatarImageUrl` is present on a friend
ariesclark Sep 20, 2026
8bca53e
chore(ci): bump actions/upload-artifact to v7
ariesclark Sep 20, 2026
fa6da13
test(friends): unfriend and withdraw when friend-request-lifecycle fails
ariesclark Sep 20, 2026
4a98da7
feat(spectral): report a nested object against the file it is written in
ariesclark Sep 20, 2026
720c71d
chore(deps): update redocly to 2.53.3
ariesclark Sep 20, 2026
cef5347
fix(friends): `friend` rate-limits with a 429
ariesclark Sep 20, 2026
510c3b3
fix(test): report the steps a goto failure action ran
ariesclark Sep 20, 2026
37d6c69
fix(authentication): `checkUserExists` rate-limits with a 429
ariesclark Sep 21, 2026
7f0c544
test(authentication): let check-user-exists-no-parameters take the ra…
ariesclark Sep 21, 2026
452aead
fix(test): drop the drift rules that only report the suite driving it…
ariesclark Sep 21, 2026
790d917
fix(ci): write the whole drift report to the log and the summary
ariesclark Sep 21, 2026
1f58f25
docs: say why test:drift names its rules and server
ariesclark Sep 21, 2026
0e9c8c3
fix(calendar): drop the no-op format on the discovery cursor
ariesclark Sep 21, 2026
6e43963
fix(calendar): `seriesId` is a calendar id, `imageUrl` is absent rath…
ariesclark Sep 21, 2026
910ad23
fix(calendar): say how to use the discovery cursor
ariesclark Sep 21, 2026
68298c9
test(friends): prove a friend request is pending with the 400 that re…
ariesclark Sep 21, 2026
15b636c
refactor(ci): call the client builds through one matrix [no release]
ariesclark Sep 21, 2026
ae604b3
Revert "refactor(ci): call the client builds through one matrix" [no …
ariesclark Sep 21, 2026
c5ca6c0
feat(ci): skip the suite on a commit marked [no test]
ariesclark Sep 21, 2026
ae67235
fix(friends): outgoingRequest lags, so the pending step asserts nothi…
ariesclark Sep 21, 2026
81ebe02
feat(redocly): port the spectral rules into the plugin
ariesclark Sep 21, 2026
2f05984
refactor(lint): replace spectral with redocly lint and cspell
ariesclark Sep 21, 2026
4489993
fix(openapi): declare the security each operation actually requires
ariesclark Sep 21, 2026
72631e0
fix(invite): `requestInvite` does not require an `instanceId`
ariesclark Sep 21, 2026
cab00cb
Document interests and preferences, and tutorial completion (#607)
ariesclark Sep 23, 2026
c5f467d
OpenAPI 3.2 & Downleveling Support (#606)
ariesclark Sep 23, 2026
3c90a14
fix(ci): stamp the nightly version into every released bundle
ariesclark Sep 23, 2026
2101244
fix: make GroupMember and EconomyAccount nullable only where null is …
ariesclark Sep 23, 2026
a54f530
feat(downlevel): write lowered fields as the registry and ecosystem e…
ariesclark Sep 23, 2026
d41129d
fix(downlevel): loosen unions of single values into an enum with open…
ariesclark Sep 23, 2026
97c8155
feat(openapi): give tags a summary and kind, and make deprecated a badge
ariesclark Sep 23, 2026
b784e37
feat(redocly): flag schema example and single-value enum in 3.1 and l…
ariesclark Sep 24, 2026
c89d6af
refactor(openapi): write schema examples as the examples list 3.1 uses
ariesclark Sep 24, 2026
641d0cd
style(openapi): write type arrays as block sequences with null last
ariesclark Sep 24, 2026
ca15ebc
fix(openapi): complete the query and moderation enums from the API's …
ariesclark Sep 24, 2026
36d98c8
fix(redocly): let a 3.2 response omit its description
ariesclark Sep 24, 2026
1866e84
refactor(openapi): drop response descriptions that only restate the s…
ariesclark Sep 24, 2026
147d9da
feat(openapi): type last_activity and last_login as a date-time or an…
ariesclark Sep 24, 2026
f3f36d5
fix(openapi): document the response bodies of group invites, world de…
ariesclark Sep 24, 2026
8b2718a
feat(openapi): name a value of any shape Unknown instead of an empty …
ariesclark Sep 24, 2026
a4ec06f
feat(redocly): prefer the Unknown schema over an empty one
ariesclark Sep 24, 2026
19d840c
docs(openapi): rewrite the API info around the SDKs, the User-Agent r…
ariesclark Sep 24, 2026
cb30bc1
feat(ci): link each released document to its other versions, the late…
ariesclark Sep 24, 2026
30b33a1
feat: point AI agents to the SDKs and to contributing upstream
ariesclark Sep 24, 2026
636dfa2
feat: stamp nightly versions and x-links in Redocly decorators
ariesclark Sep 24, 2026
76d656f
fix(x-links): write the links after info.description
ariesclark Sep 24, 2026
a09c1e9
feat: discourage patching the specification locally
ariesclark Sep 24, 2026
73bac55
fix(x-links): skip documents without an info object
ariesclark Sep 28, 2026
e063f75
feat(schema-title): require PascalCase titles that match the filename
ariesclark Sep 28, 2026
59b478e
chore(redocly): enable four built-in rules and drop parameter-descrip…
ariesclark Sep 28, 2026
4eaba47
fix(users): document the allowWorldsToCountFriendsInInstance setting
ariesclark Sep 28, 2026
de7738a
test(interests): drop the ignored-keys probe and the claim it backed
ariesclark Sep 28, 2026
153b70c
fix(instances): document displayVibeId
ariesclark Sep 28, 2026
5b63534
fix(infoPush): document content shelves and promotions
ariesclark Sep 28, 2026
b3c6983
chore(deps): update Redocly to 2.54.3
ariesclark Sep 28, 2026
a352e92
test(calendar): delete the group when creating its event fails
ariesclark Sep 28, 2026
b702a30
test: delete what a lifecycle workflow created when a later step fails
ariesclark Sep 28, 2026
d1e1928
test: run the group workflows in the group named by VRCHAT_GROUP_ID
ariesclark Sep 28, 2026
6cfb782
fix(schemas): allow null ModerationReport.evidenceRequired
ariesclark Sep 29, 2026
faf96bc
fix(schemas): document ModerationReport.created
ariesclark Sep 29, 2026
4c6b776
test: submit, find and delete a moderation report against the test ac…
ariesclark Sep 29, 2026
efa91ce
fix(schemas): allow null ModerationReport.description
ariesclark Sep 29, 2026
c1cb4ee
chore: require an issue form and add a pull request template
ariesclark Sep 29, 2026
7ac592a
chore: stop warning on scalar properties without an example
ariesclark Sep 30, 2026
ba9e00d
test: read every friend through getUser, friend status, mutuals and g…
ariesclark Oct 1, 2026
845c0d3
fix(schemas): document User.discordId and LimitedUserGroups.storeId
ariesclark Oct 1, 2026
fef7b64
test: follow online friends into their instances and round-trip a not…
ariesclark Oct 1, 2026
9fae779
fix(responses): document the string updateUserNote returns when it cl…
ariesclark Oct 1, 2026
393ad7a
fix(users): document the accountStanding field on the current user
ariesclark Oct 3, 2026
e365b46
Audit Log Typings (#611)
lillithrosepup Oct 7, 2026
2bd9c82
fix(schemas): make LimitedUserInstance avatar fields optional (#612)
Rexios80 Oct 7, 2026
70c35d9
chore: release 1.22.0 (#613)
Rexios80 Oct 7, 2026
4ab3fac
chore(ci): number nightlies in sequence and release from stable [no r…
ariesclark Oct 7, 2026
e5c3d37
fix(ci): lint what a push changed since its before commit [no release]
ariesclark Oct 7, 2026
81d81df
fix(ci): release stable only when its declared version is untagged [n…
ariesclark Oct 7, 2026
167aec6
chore(ci): skip the live API tests on stable pushes [no release]
ariesclark Oct 7, 2026
bbf7e80
chore(ci): run the live API tests only for main [no release]
ariesclark Oct 7, 2026
a0a9aa6
fix(downlevel): fold each union member's allOf into the loosened schema
ariesclark Oct 7, 2026
ed41a8c
fix(test): leave allOf parts open when closing the test bundle's schemas
ariesclark Oct 7, 2026
4fd66b0
fix(test): drop discriminators from the test bundle
ariesclark Oct 7, 2026
9205b77
fix(schemas): make GroupAuditLogEntry the discriminated union itself
ariesclark Oct 7, 2026
04a7a39
fix(ci): queue pushes per branch so versions can't collide [no release]
ariesclark Oct 7, 2026
af4083f
Merge branch 'pr-597' into review-597
ariesclark Oct 7, 2026
e6b3d7a
fix(instances): write calendarEntryId as a nullable CalendarID
ariesclark Oct 7, 2026
a68a22d
test: carry x-security on the API steps of the update-instance workflows
ariesclark Oct 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* text=auto eol=lf
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Ask on Discord
url: https://discord.gg/qjZE9C9fkB
about: Questions about using the API or one of the libraries.
- name: Report a bug in one library
url: https://github.com/orgs/vrchatapi/repositories
about: Every library is generated from this specification, so a response one of them can't parse belongs here. A bug in a library's own code belongs in its repository.
31 changes: 31 additions & 0 deletions .github/ISSUE_TEMPLATE/missing-from-specification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Missing from the specification
description: An endpoint, parameter or field VRChat supports that the specification doesn't describe.
labels:
- "Type: Enhancement"
body:
- type: input
id: request
attributes:
label: Request
description: The method and path.
placeholder: GET /instanceCategories
validations:
required: true
- type: textarea
id: missing
attributes:
label: What's missing
description: The endpoint, parameter or field, and what it does.
validations:
required: true
- type: textarea
id: capture
attributes:
label: Request and response
description: A request you sent and the response VRChat returned. Redact anything personal, but keep each value's type.
render: text
- type: textarea
id: source
attributes:
label: Where it comes from
description: Where you saw it, such as the VRChat client, the website or a Developer Update. Link it if you can.
35 changes: 35 additions & 0 deletions .github/ISSUE_TEMPLATE/response-mismatch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: Response doesn't match
description: A library fails to parse a response, or VRChat returns a field, type or value the specification doesn't describe.
labels:
- "Type: Bug"
body:
- type: markdown
attributes:
value: A library's error names the field but not the value that broke it. The raw response is what lets us fix it.
- type: input
id: operation
attributes:
label: Operation
description: The operation id or the request.
placeholder: getModerationReports, or GET /moderationReports
validations:
required: true
- type: textarea
id: response
attributes:
label: Response body
description: The JSON VRChat returned, or the object within it that failed. Redact anything personal, but keep each value's type. Replace a string with another string, and leave `null` as `null`.
render: json
validations:
required: true
- type: textarea
id: error
attributes:
label: Error
description: The error your library raised, if any.
render: text
- type: input
id: library
attributes:
label: Library and version
placeholder: vrchatapi-csharp 1.21.0
9 changes: 9 additions & 0 deletions .github/ISSUE_TEMPLATE/something-else.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name: Something else
description: A wrong description, a problem with the published bundles, or anything neither form above covers.
body:
- type: textarea
id: description
attributes:
label: What's wrong
validations:
required: true
9 changes: 9 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Closes #

## Evidence

<!-- The workflow in test/arazzo.yaml that captures the change, or the issue carrying the response it comes from. -->

- [ ] Every property, type and example comes from a captured response
- [ ] `pnpm lint` passes
- [ ] `pnpm test -w session -w <workflow>` passes
112 changes: 87 additions & 25 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ on:
push:
branches:
- main
- stable
pull_request:
schedule:
- cron: "17 7 * * *"
workflow_dispatch:

concurrency:
group: ${{ github.event_name == 'push' && format('{0}-{1}', github.workflow, github.ref) || github.run_id }}
cancel-in-progress: false
queue: max

env:
GH_TOKEN: ${{ github.token }}

Expand All @@ -24,9 +30,9 @@ jobs:
runtime: bun@latest
cache: true

- if: github.event_name == 'push'
- if: github.event_name == 'push' && github.event.before != '0000000000000000000000000000000000000000'
run: |
changes=$(git diff --name-only --diff-filter=d "${{ github.event.commits[0].id }}~1" "${{ github.event.commits[0].id }}")
changes=$(git diff --name-only --diff-filter=d "${{ github.event.before }}" "${{ github.sha }}")
{
echo 'changes<<eof_${{ github.run_id }}'
echo "$changes"
Expand Down Expand Up @@ -54,6 +60,9 @@ jobs:
continue-on-error: true
run: pnpm run lint-ci

- name: test and build redocly-plugin-downlevel
run: pnpm run test:downlevel

- name: assert no unused paths
if: env.changes != ''
run: |
Expand All @@ -77,16 +86,52 @@ jobs:
bundle:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
outputs:
release: ${{ steps.version.outputs.release }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- uses: pnpm/setup@v2
with:
runtime: bun@latest
cache: true

- name: version the build for the branch it releases from
id: version
run: |
declared=$(yq -r '.info.version' openapi/openapi.yaml)
latest=$(git tag --list 'v*' | sed 's/^v//' | xargs -r pnpm -s semver --range '*' | tail -n 1 || true)

release=true

if [ "$GITHUB_REF_NAME" = stable ]; then
version=$declared

if ! pnpm -s semver "$declared" > /dev/null; then
echo "::error::$declared is not a version"
exit 1
elif git rev-parse --quiet --verify "refs/tags/v$declared" > /dev/null; then
release=false
elif [ -n "$latest" ] && pnpm -s semver --range "<$latest" "$declared" > /dev/null; then
echo "::error::$declared is below the latest release, $latest"
exit 1
fi
else
base=$(pnpm -s semver --increment patch "${latest:-$declared}")
highest=$(git tag --list "v$base-nightly.*" | sed "s/^v$base-nightly\.//" | grep -xE '[0-9]+' | sort -n | tail -n 1 || true)
version="$base-nightly.$(( ${highest:-0} + 1 ))"
fi

echo "version=$version" >> "$GITHUB_ENV"
echo "release=$release" >> "$GITHUB_OUTPUT"

- run: bun --bun run bundle

- name: lint the downleveled bundles as the version they declare
run: bun --bun run test:versions

- uses: actions/github-script@v9
with:
script: |
Expand Down Expand Up @@ -132,19 +177,14 @@ jobs:
needs:
- lint
- bundle
if: ${{ !failure() && !cancelled() && github.event_name != 'schedule' && github.ref == 'refs/heads/main' }}
if: ${{ !failure() && !cancelled() && github.event_name != 'schedule' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/stable') && needs.bundle.outputs.release == 'true' && !contains(github.event.head_commit.message, '[no release]') }}
concurrency:
group: release
outputs:
version: ${{ steps.metadata.outputs.version }}

steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0

- uses: pnpm/setup@v2
with:
runtime: bun@latest
cache: true

- uses: actions/download-artifact@v8
with:
Expand All @@ -156,17 +196,10 @@ jobs:
run: |
version=$(jq -r '.info.version' dist/openapi.json)

version_sha=$(
git rev-list -n 1 "v$version" 2>/dev/null \
|| git rev-list -n 1 "release/$version" 2>/dev/null \
|| echo ""
)

if [ "$version_sha" == "" ]; then
echo "prerelease=false" >> $GITHUB_ENV
else
if [[ "$version" == *-nightly.* ]]; then
echo "prerelease=true" >> $GITHUB_ENV
version=$(pnpm semver $version -i)-nightly.$(git rev-list --count "$version_sha"..HEAD)
else
echo "prerelease=false" >> $GITHUB_ENV
fi

echo "version=$version" >> $GITHUB_ENV
Expand All @@ -179,13 +212,16 @@ jobs:
- name: create release (nightly)
if: env.prerelease == 'true'
run: |
jq --arg v "${{ env.version }}" '.info.version = $v' dist/openapi.json > dist/.openapi.json && mv dist/.openapi.json dist/openapi.json
yq eval ".info.version = \"${{ env.version }}\"" -i dist/openapi.yaml

gh release create v${{ env.version }} dist/* \
--generate-notes \
--prerelease

- name: refresh the nightly release
if: github.ref == 'refs/heads/main'
run: |
gh release upload nightly dist/* --clobber
gh release edit nightly --notes "The latest build from main, currently v${{ env.version }}. Its files are replaced whenever a new build is published."

release_dispatch:
uses: ./.github/workflows/release_dispatch.yaml
needs: release
Expand All @@ -194,7 +230,7 @@ jobs:
version: ${{ needs.release.outputs.version }}

test:
if: github.event_name != 'pull_request'
if: github.ref == 'refs/heads/main' && !contains(github.event.head_commit.message, '[no test]')
runs-on: ubuntu-latest
concurrency:
group: test
Expand All @@ -215,6 +251,32 @@ jobs:
VRCHAT_PASSWORD: ${{ secrets.VRCHAT_PASSWORD }}
VRCHAT_TOTP_SECRET: ${{ secrets.VRCHAT_TOTP_SECRET }}
VRCHAT_FRIEND_ID: ${{ secrets.VRCHAT_FRIEND_ID }}
VRCHAT_GROUP_ID: ${{ secrets.VRCHAT_GROUP_ID }}

- if: "!cancelled()"
uses: actions/upload-artifact@v7
with:
name: respect-report
path: test/.out/respect.json
retention-days: 1

- if: "!cancelled()"
run: pnpm test:drift >> "$GITHUB_STEP_SUMMARY"
timeout-minutes: 2
run: sh test/report.sh --format github

- if: "!cancelled()"
timeout-minutes: 2
run: sh test/report.sh >> "$GITHUB_STEP_SUMMARY"

- if: "!cancelled()"
timeout-minutes: 5
run: |
status=0
pnpm -s test:drift --max-findings 1000 --output test/.out/drift.txt || status=$?
cat test/.out/drift.txt
{
printf '### Drift\n\n```\n'
cat test/.out/drift.txt
printf '```\n'
} >> "$GITHUB_STEP_SUMMARY"
exit $status
Loading