-
Notifications
You must be signed in to change notification settings - Fork 33
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
feat: add cURL code samples #154
Conversation
Fixes #150 Signed-off-by: Hilton Chain <hako@ultrarare.space>
@rakino How are all of these added? Is there an automated process or did you add all of them manually? |
@Foorack Since I have no previous experience with OpenAPI, I tried the OpenApi code sample generator first to get an impression, then review (with my VRChat account) and edit the samples by hand. FYI, below attaching the output. generator output (partial due to length limit)openapi: 3.0.3
info:
title: VRChat API Documentation
version: 1.7.1
contact:
name: Unofficial VRChat API Documentation Project
url: 'https://github.com/VRChatAPI'
email: me@ariesclark.com
termsOfService: 'https://vrchat.com/legal/'
license:
url: 'https://github.com/vrchatapi/specification/blob/master/LICENSE'
name: The MIT License (MIT)
description: "![VRChat API Banner](https://vrchatapi.github.io/assets/img/api_banner_1500x400.png)\n\n# Welcome to the VRChat API\n\nBefore we begin, we would like to state this is a **COMMUNITY DRIVEN PROJECT**.\nThis means that everything you read on here was written by the community itself and is **not** officially supported by VRChat.\nThe documentation is provided \"AS IS\", and any action you take towards VRChat is completely your own responsibility.\n\nThe documentation and additional libraries SHALL ONLY be used for applications interacting with VRChat's API in accordance\nwith their [Terms of Service](https://hello.vrchat.com/legal) and [Community Guidelines](https://hello.vrchat.com/community-guidelines), and MUST NOT be used for modifying the client, \"avatar ripping\", or other illegal activities.\nMalicious usage or spamming the API may result in account termination.\nCertain parts of the API are also more sensitive than others, for example moderation, so please tread extra carefully and read the warnings when present.\n\n![Tupper Policy on API](https://i.imgur.com/yLlW7Ok.png)\n\nFinally, use of the API using applications other than the approved methods (website, VRChat application, Unity SDK) is not officially supported.\nVRChat provides no guarantee or support for external applications using the API. Access to API endpoints may break **at any time, without notice**.\nTherefore, please **do not ping** VRChat Staff in the VRChat Discord if you are having API problems, as they do not provide API support.\nWe will make a best effort in keeping this documentation and associated language libraries up to date, but things might be outdated or missing.\nIf you find that something is no longer valid, please contact us on Discord or [create an issue](https://github.com/vrchatapi/specification/issues) and tell us so we can fix it.\n\n# Getting Started\n\nThe VRChat API can be used to programmatically retrieve or update information regarding your profile, friends, avatars, worlds and more.\nThe API consists of two parts, \"Photon\" which is only used in-game, and the \"Web API\" which is used by both the game and the website.\nThis documentation focuses only on the Web API.\n\nThe API is designed around the REST ideology, providing semi-simple and usually predictable URIs to access and modify objects.\nRequests support standard HTTP methods like GET, PUT, POST, and DELETE and standard status codes.\nResponse bodies are always UTF-8 encoded JSON objects, unless explicitly documented otherwise.\n\n<div class=\"callout callout-error\">\n <strong>\U0001F6D1 Warning! Do not touch Photon!</strong><br>\n Photon is only used by the in-game client and should <b>not</b> be touched. Doing so may result in permanent account termination.\n</div>\n\n<div class=\"callout callout-info\">\n <strong>ℹ️ API Key and Authentication</strong><br>\n The API Key has always been the same and is currently <code>JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26</code>.\n Read <a href=\"#tag--authentication\">Authentication</a> for how to log in.\n</div>\n\n# Using the API\n\nFor simply exploring what the API can do it is strongly recommended to download [Insomnia](https://insomnia.rest/download), a free and open-source\nAPI client that's great for sending requests to the API in an orderly fashion.\nInsomnia allows you to send data in the format that's required for VRChat's API.\nIt is also possible to try out the API in your browser, by first logging in at [vrchat.com/home](https://vrchat.com/home/) and then going to\n[vrchat.com/api/1/auth/user](https://vrchat.com/api/1/auth/user), but the information will be much harder to work with.\n\nFor more permanent operation such as software development it is instead recommended to use one of the existing language SDKs.\nThis community project maintains API libraries in several languages, which allows you to interact with the API with simple function calls\nrather than having to implement the HTTP protocol yourself. Most of these libraries are automatically generated from the API specification,\nsometimes with additional helpful wrapper code to make usage easier. This allows them to be almost automatically updated and expanded upon\nas soon as a new feature is introduced in the specification itself. The libraries can be found on [GitHub](https://github.com/vrchatapi) or following:\n\n* [NodeJS (JavaScript)](https://www.npmjs.com/package/vrchat)\n* [Dart](https://pub.dev/packages/vrchat_dart)\n* [Rust](https://crates.io/crates/vrchatapi)\n* [C#](https://github.com/vrchatapi/vrchatapi-csharp)\n* [Python](https://github.com/vrchatapi/vrchatapi-python)\n\n# Pagination\n\nMost endpoints enforce pagination, meaning they will only return 10 entries by default, and never more than 100.<br>\nUsing both the limit and offset parameters allows you to easily paginate through a large number of objects.\n\n| Query Parameter | Type | Description |\n| ----------|--|------- |\n| `n` | integer | The number of objects to return. This value often defaults to 10. Highest limit is always 100.|\n| `offset` | integer | A zero-based offset from the default object sorting.|\n\nIf a request returns fewer objects than the `limit` parameter, there are no more items available to return.\n\n# Contribution\n\nDo you want to get involved in the documentation effort? Do you want to help improve one of the language API libraries?\nThis project is an [OPEN Open Source Project](https://openopensource.org)! This means that individuals making significant and valuable contributions are given\ncommit-access to the project. It also means we are very open and welcoming of new people making contributions, unlike some more guarded open-source projects.\n\n[![Discord](https://img.shields.io/static/v1?label=vrchatapi&message=discord&color=blueviolet&style=for-the-badge)](https://discord.gg/qjZE9C9fkB)"
servers:
- url: 'https://api.vrchat.cloud/api/1'
paths:
/auth/exists:
get:
summary: Check User Exists
tags:
- authentication
responses:
'200':
description: Returns a response if a user exists or not.
content:
application/json:
schema:
description: >-
Status object representing if a queried user by username or
userId exists or not. This model is primarily used by the
`/auth/exists` endpoint, which in turn is used during
registration. Please see the documentation on that endpoint
for more information on usage.
properties:
userExists:
default: false
description: Status if a user exist with that username or userId.
type: boolean
required:
- userExists
title: UserExists
type: object
'400':
description: Error response when missing at least 1 of the required parameters.
content:
application/json:
schema: &ref_2
properties:
error: &ref_6
properties:
message:
minLength: 1
type: string
status_code:
minimum: 100
type: integer
required:
- status_code
title: Response
type: object
title: Error
type: object
examples:
400 At Least One Parameter Required:
value:
error:
message: '"username, email, or displayName required"'
status_code: 400
operationId: checkUserExists
parameters:
- name: email
in: query
required: false
schema:
type: string
description: Filter by email.
- name: displayName
in: query
required: false
schema:
type: string
description: Filter by displayName.
- &ref_10
name: userId
in: query
required: false
schema:
type: string
description: Filter by UserID.
- name: excludeUserId
in: query
required: false
schema:
type: string
description: Exclude by UserID.
description: >-
Checks if a user by a given `username`, `displayName` or `email` exist.
This is used during registration to check if a username has already been
taken, during change of displayName to check if a displayName is
available, and during change of email to check if the email is already
used. In the later two cases the `excludeUserId` is used to exclude
oneself, otherwise the result would always be true.
It is **REQUIRED** to include **AT LEAST** `username`, `displayName`
**or** `email` query parameter. Although they can be combined - in
addition with `excludeUserId` (generally to exclude yourself) - to
further fine-tune the search.
security:
- apiKeyCookie: []
x-codeSamples:
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/auth/exists?email=SOME_STRING_VALUE&displayName=SOME_STRING_VALUE&userId=SOME_STRING_VALUE&excludeUserId=SOME_STRING_VALUE");
CURLcode ret = curl_easy_perform(hnd);
/auth/user:
get:
summary: Login and/or Get Current User Info
tags:
- authentication
responses:
'200':
description: OK
content:
application/json:
schema: &ref_7
properties:
acceptedTOSVersion:
minimum: 0
example: 7
type: integer
accountDeletionDate:
format: date
nullable: true
type: string
activeFriends:
items: &ref_1
example: usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469
title: UserID
type: string
description: >-
A users unique ID, usually in the form of
`usr_c1644b5b-3ca4-45b4-97c6-a2a0de70d469`. Legacy
players can have old IDs in the form of `8JoV9XEdpo`.
The ID can never be changed.
type: array
allowAvatarCopying:
type: boolean
bio:
type: string
bioLinks:
items:
type: string
type: array
currentAvatar: &ref_0
example: avtr_912d66a4-4714-43b8-8407-7de2cafbf55b
pattern: >-
avtr_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}
title: AvatarID
type: string
currentAvatarAssetUrl:
type: string
currentAvatarImageUrl: &ref_55
description: 'When profilePicOverride is not empty, use it instead.'
example: >-
https://api.vrchat.cloud/api/1/file/file_ae46d521-7281-4b38-b365-804b32a1d6a7/1/file
title: CurrentAvatarImageUrl
type: string
currentAvatarThumbnailImageUrl: &ref_56
description: 'When profilePicOverride is not empty, use it instead.'
example: >-
https://api.vrchat.cloud/api/1/image/file_aae83ed9-d42d-4d72-9f4b-9f1e41ed17e1/1/256
title: CurrentAvatarThumbnailImageUrl
type: string
date_joined:
format: date
type: string
developerType: &ref_57
default: none
description: |-
"none" User is a normal user
"trusted" Unknown
"internal" Is a VRChat Developer
"moderator" Is a VRChat Moderator
Staff can hide their developerType at will.
enum:
- none
- trusted
- internal
- moderator
title: DeveloperType
type: string
displayName:
type: string
emailVerified:
type: boolean
fallbackAvatar: *ref_0
friendGroupNames:
deprecated: true
description: Always empty array.
items:
type: string
type: array
friendKey:
type: string
friends:
items: *ref_1
type: array
hasBirthday:
type: boolean
hasEmail:
type: boolean
hasLoggedInFromClient:
type: boolean
hasPendingEmail:
type: boolean
homeLocation: &ref_69
example: wrld_ba913a96-fac4-4048-a062-9aa5db092812
pattern: >-
(^$|offline|(wrld|wld)_[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})
title: WorldID
type: string
description: >-
WorldID be "offline" on User profiles if you are not
friends with that user.
id: *ref_1
isFriend:
default: false
type: boolean
last_login:
format: date-time
type: string
last_platform: &ref_9
description: >-
This can be `standalonewindows` or `android`, but can also
pretty much be any random Unity verison such as
`2019.2.4-801-Release` or `2019.2.2-772-Release` or even
`unknownplatform`.
example: standalonewindows
title: Platform
type: string
obfuscatedEmail:
type: string
obfuscatedPendingEmail:
type: string
oculusId:
type: string
offlineFriends:
items: *ref_1
type: array
onlineFriends:
items: *ref_1
type: array
pastDisplayNames:
description: ' '
items:
properties:
displayName:
minLength: 1
type: string
updated_at:
format: date-time
type: string
required:
- displayName
- updated_at
title: PastDisplayName
type: object
type: array
profilePicOverride:
type: string
state: &ref_89
default: offline
description: >-
* "online" User is online in VRChat
* "active" User is online, but not in VRChat
* "offline" User is offline
Always offline when returned through `getCurrentUser`
(/auth/user).
enum:
- offline
- active
- online
title: UserState
type: string
status: &ref_58
type: string
description: >-
Defines the User's current status, for example "ask me",
"join me" or "offline. This status is a combined indicator
of their online activity and privacy preference.
enum:
- active
- join me
- ask me
- busy
- offline
title: UserStatus
default: offline
statusDescription:
type: string
statusFirstTime:
type: boolean
statusHistory:
items:
type: string
type: array
steamDetails:
type: object
steamId:
type: string
tags:
items: &ref_8
description: >-
Tags are a way to grant various access, assign
restrictions or other kinds of metadata to various to
objects such as worlds, users and avatars.
System tags starting with `system_` are granted
automatically by the system, while admin tags with
`admin_` are granted manually. More prefixes such as
`language_ ` (to indicate that a player can speak the
tagged language), and `author_tag_` (provided by a world
author for search and sorting) exist as well.
minLength: 1
title: Tag
type: string
type: array
twoFactorAuthEnabled:
type: boolean
twoFactorAuthEnabledDate:
format: date-time
nullable: true
type: string
unsubscribe:
type: boolean
userIcon:
type: string
username:
type: string
required:
- id
- username
- displayName
- userIcon
- bio
- bioLinks
- profilePicOverride
- statusDescription
- pastDisplayNames
- hasEmail
- hasPendingEmail
- obfuscatedEmail
- obfuscatedPendingEmail
- emailVerified
- hasBirthday
- unsubscribe
- statusHistory
- statusFirstTime
- friends
- friendGroupNames
- currentAvatarImageUrl
- currentAvatarThumbnailImageUrl
- currentAvatar
- currentAvatarAssetUrl
- acceptedTOSVersion
- steamId
- steamDetails
- oculusId
- hasLoggedInFromClient
- homeLocation
- twoFactorAuthEnabled
- state
- tags
- developerType
- last_login
- last_platform
- allowAvatarCopying
- status
- date_joined
- isFriend
- friendKey
title: CurrentUser
type: object
headers:
Set-Cookie:
schema:
type: string
example: >-
auth=authcookie_00000000-0000-0000-0000-000000000000;
Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly
description: Successful authentication returns an `auth` cookie.
\0Set-Cookie:
schema:
type: string
default: apiKey=JlE5Jldo5Jibnk5O5hTx6XVqsJu4WJ26; Path=/
description: >-
This endpoint **always** sets the `apiKey` irrespective if it is
already set.
'401': &ref_3
description: Error response due to missing apiKey or auth cookie.
content:
application/json:
schema: *ref_2
examples:
Missing Credentials Example:
value:
error:
message: '"Missing Credentials"'
status_code: 401
operationId: getCurrentUser
description: >-
This endpoint does the following two operations:
1) Checks if you are already logged in by looking for a valid `auth` cookie. If you are have a valid auth cookie then no additional auth-related actions are taken. If you are **not** logged in then it will log you in with the `Authorization` header and set the `auth` cookie. The `auth` cookie will only be sent once.
2) If logged in, this function will also return the CurrentUser object containing detailed information about the currently logged in user.
**WARNING: Session Limit:** Each authentication with login credentials
counts as a separate session, out of which you have a limited amount.
Make sure to save and reuse the `auth` cookie if you are often
restarting the program. The provided API libraries automatically save
cookies during runtime, but does not persist during restart. While it
can be fine to use username/password during development, expect in
production to very fast run into the rate-limit and be temporarily
blocked from making new sessions until older ones expire. The exact
number of simultaneous sessions is unknown/undisclosed.
parameters: []
security:
- authHeader: []
- authHeader: []
twoFactorAuthCookie: []
- authCookie: []
x-codeSamples:
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/auth/user");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Authorization: Basic
REPLACE_BASIC_AUTH");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
CURLcode ret = curl_easy_perform(hnd);
/auth/twofactorauth/totp/verify:
post:
summary: Verify 2FA code
operationId: verify2FA
responses:
'200': &ref_4
description: OK
content:
application/json:
schema:
title: Verify2FAResult
type: object
properties:
verified:
type: boolean
required:
- verified
headers:
Set-Cookie:
schema:
type: string
example: >-
twoFactorAuth=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;
Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/; HttpOnly
description: >-
Provides a `twoFactorAuth` cookie, which can be used to bypasses
the 2FA requirement for future logins on the same device.
'401': *ref_3
requestBody:
content:
application/json:
schema: &ref_5
title: TwoFactorAuthCode
type: object
properties:
code:
type: string
required:
- code
examples: {}
description: >-
Finishes the login sequence with a normal 2FA-generated code for
accounts with 2FA-protection enabled.
tags:
- authentication
security:
- authCookie: []
parameters: []
x-codeSamples:
- lang: cURL
source: |
curl \
--cookie "auth={authCookie}" \
--header "Content-Type: application/json" \
--data '{"code": "string"}'
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/auth/twofactorauth/totp/verify");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "content-type:
application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\"code\":\"string\"}");
CURLcode ret = curl_easy_perform(hnd);
/auth/twofactorauth/otp/verify:
post:
summary: Verify 2FA code with Recovery code
operationId: verifyRecoveryCode
responses:
'200': *ref_4
'401': *ref_3
requestBody:
content:
application/json:
schema: *ref_5
examples: {}
description: >-
Finishes the login sequence with an OTP (One Time Password) recovery
code for accounts with 2FA-protection enabled.
tags:
- authentication
security:
- authCookie: []
x-codeSamples:
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/auth/twofactorauth/otp/verify");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "content-type:
application/json");
curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\"code\":\"string\"}");
CURLcode ret = curl_easy_perform(hnd);
/auth:
get:
summary: Verify Auth Token
tags:
- authentication
responses:
'200':
description: Returns wether a provided auth token is valid or not.
content:
application/json:
schema:
title: VerifyAuthToken
type: object
properties:
ok:
type: boolean
token:
type: string
minLength: 1
required:
- ok
- token
'401': *ref_3
operationId: verifyAuthToken
parameters: []
description: Verify whether the currently provided Auth Token is valid.
security:
- authCookie: []
x-codeSamples:
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/auth");
CURLcode ret = curl_easy_perform(hnd);
/logout:
put:
summary: Logout
operationId: logout
responses:
'200':
description: OK
content:
application/json:
schema: &ref_42
properties:
success: *ref_6
title: Success
type: object
examples:
Logout Success:
value:
success:
message: Ok!
status_code: 200
headers:
Set-Cookie:
schema:
type: string
default: 'auth=; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/'
description: Clears the `auth` cookie.
\0Set-Cookie:
schema:
type: string
default: 'age=; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/'
description: Clears the `age` cookie.
\0\0Set-Cookie:
schema:
type: string
default: 'tos=; Expires=Tue, 01 Jan 2030 00:00:00 GMT; Path=/'
description: Clears the `tos` cookie.
'401': *ref_3
description: Invalidates the login session.
security:
- authCookie: []
tags:
- authentication
x-codeSamples:
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/logout");
CURLcode ret = curl_easy_perform(hnd);
'/user/{userId}/delete':
parameters:
- &ref_44
name: userId
in: path
required: true
schema:
type: string
put:
summary: Delete User
operationId: deleteUser
responses:
'200':
description: OK
content:
application/json:
schema: *ref_7
'401': *ref_3
tags:
- authentication
description: >-
Deletes the account with given ID. Normal users only have permission to
delete their own account. Account deletion is 14 days from this request,
and will be cancelled if you do an authenticated request with the
account afterwards.
**VRC+ NOTE:** Despite the 14-days cooldown, any VRC+ subscription will
be cancelled **immediately**.
**METHOD NOTE:** Despite this being a Delete action, the method type
required is PUT.
security:
- apiKeyCookie: []
authCookie: []
x-codeSamples:
- lang: C + Libcurl
source: >-
CURL *hnd = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "PUT");
curl_easy_setopt(hnd, CURLOPT_URL,
"https://api.vrchat.cloud/api/1/user/%7BuserId%7D/delete");
CURLcode ret = curl_easy_perform(hnd); |
Ok, thank you. I was only worried about future code-maintainability. But this looks good. Thanks for the work! ❤️ |
Fixes #150
Related: vrchatapi/vrchatapi.github.io#120