OpenAPI definition
BulletForceHax provides documentation of the Bullet Force HTTP API surface in the form of an OpenAPI definition with accompanying Swagger UI interface. BulletForceHax developers maintain this OpenAPI definition on a best-effort basis, meaning it may not be up to date or may miss various significant endpoints.
Generating OpenAPI clients
One use for OpenAPI definitions is to automatically generate API clients. These clients allow programmatic access to the API through a more high-level API with code that's generated at build-time.
The Bullet Force API is problematic in this regard because it returns a text/html
content-types for JSON-formatted responses. OpenAPI client generators can't reasonably predict this, and some use a generic byte stream or string response type instead. You can work around this in several ways:
- Modify the OpenAPI definition to specify
application/json
responses instead. This tricks the client generator into generating JSON parsing code, although this causes problems with generated clients that check the response's return type at runtime. - Manually parse the returned byte stream or string into the correct data type. The OpenAPI definition still contains all return types, so client generators should include those models in their generate code too.
OpenAPI definition
Below is a copy of the full OpenAPI definition as it was while during compilation of this book. You can also find this hosted online or in the GitHub repository.
openapi: 3.0.3 # latest version supported by progenitor
info:
title: Bullet Force
description: |-
This OpenAPI definition describes the internal Bullet Force API.
Note that this is a best-effort replication of the API. It may be inaccurate or incomplete.
contact:
name: Variant9
url: https://github.com/holly-hacker/bulletforcehaxv3
# TODO: license
version: 1.0.0
servers:
- url: https://server.blayzegames.com/OnlineAccountSystem
tags:
- name: Account
description: API calls related to accounts and authentication
- name: Chat
description: API calls related to lobby chat
paths:
# Login
/login.php:
post:
summary: Checks if a login is valid
description: |-
Checks whether a login is valid and returns some info about the account.
operationId: login
tags: ["Account"]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
username:
$ref: "#/components/schemas/UserName"
password:
$ref: "#/components/schemas/UserPassword"
store:
type: string
description: Which game client is used to execute this request
example: "BALYZE_WEB" # typo is expected
useJSON:
type: boolean
description: Determines the response type
example: true
locale:
type: string
description: The user's language
example: "english"
tutorialr:
type: number
example: 1
crazyGamesToken:
type: string
description: Key is present but has no value
responses:
"200":
description: Success and error responses?
content:
text/html:
schema:
type: object
properties:
acnumber:
type: string
format: number
example: "123456789"
isTutorial:
type: number
format: boolean
example: 0
locale:
type: string
example: "english"
popup:
type: boolean
example: false
status:
type: number
example: 1
/get_multiplayer_auth_code.php:
post:
summary: Get a code to authenticate a user in a match
description: |-
Returns an authentication code that should be sent using the [RpcSendMultiplayerAuthToken](https://variant9.dev/BulletForceHaxV3/BulletForceInternal/PUN/ListOfRpcCalls.html#RpcSendMultiplayerAuthToken) RPC call.
This token is only valid until a new token is generated.
operationId: getMultiplayerAuthCode
tags: ["Account"]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
username:
$ref: "#/components/schemas/UserName"
required: true
password:
$ref: "#/components/schemas/UserPassword"
required: true
responses:
"200":
description: This request always returns 200, regardless of success.
content:
text/html:
schema:
type: string
examples:
success:
description: "Success response, containing a hex-encoded token"
value: "12345678abcde"
error:
description: "Error response, containing an empty string"
value: ""
# Chat
/get_lobby_chatV2.php:
post:
summary: Fetch in-game lobby chat
description: |-
Returns the in-game lobby chat which is seen when loading into the game.
Note that this is not the chat you see while in a match. In a match, chat messages are received using the [RpcSendChatMessage](https://variant9.dev/BulletForceHaxV3/BulletForceInternal/PUN/ListOfRpcCalls.html#RpcSendChatMessage) RPC call.
operationId: getLobbyChatV2
tags: ["Chat"]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
platform:
type: string
description: The platform the user is using
example: WebGLPlayer
username:
$ref: "#/components/schemas/UserName"
required: true # works without this but prints error
password:
$ref: "#/components/schemas/UserPassword"
server:
type: string
format: uri
description: The lobby server the user is using
example: wss://game-ca-1.blayzegames.com
responses:
"200":
description: |-
Contains JSON-encoded messages and some metadata.
Note that the content type is `text/html`, but the content is encoded as JSON.
content:
text/html: # BF does not set correct content type headers
schema:
type: object
properties:
messages:
type: array
maxItems: 50
items:
$ref: "#/components/schemas/ChatMessage"
playersOnline:
type: string
format: number
minimum: 0
playersOnlineInServer:
type: number
minimum: 0
/send_lobby_chatV2.php:
post:
summary: Send a chat message
description: |-
Used to send a chat message. Returns a list of the new chat messages in response.
operationId: sendLobbyChatV2
tags: ["Chat"]
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
properties:
platform:
type: string
description: The platform the user is using
example: WebGLPlayer
username:
$ref: "#/components/schemas/UserName"
password:
$ref: "#/components/schemas/UserPassword"
chat:
type: string
format: uri
description: The chat message to send
example: "Hello world!"
server:
type: string
format: uri
description: The lobby server the user is using
example: wss://game-ca-1.blayzegames.com
responses:
"200":
description: |-
Contains JSON-encoded messages, including the newly sent message.
Note that the content type is `text/html`, but the content is encoded as JSON.
content:
text/html: # BF does not set correct content type headers
schema:
type: object
properties:
messages:
type: array
maxItems: 50
items:
$ref: "#/components/schemas/ChatMessage"
components:
schemas:
UserName:
type: string
description: The player's username
example: "PC-Username"
UserPassword:
type: string
description: The player's password hashed with SHA512, encoded as uppercase hexadecimal.
example: "B109F3BBBC244EB82441917ED06D618B9008DD09B3BEFD1B5E07394C706A8BB980B1D7785E5976EC049B46DF5F1326AF5A2EA6D103FD07C95385FFAB0CACBC86"
ChatMessage:
type: object
properties:
message:
type: string
description: The content of the chat message. This includes the sender's username.
example: "PlayerName: <color=silver>Hello world!</color>"
time:
type: number
format: timestamp
description: The Unix timestamp when the message was sent, in seconds.
example: 1735689600
username:
type: string
description: The username of the person that sent the chat message.
example: "PlayerName"
externalDocs:
url: https://variant9.dev/BulletForceHaxV3/