Skip to content

Frequently Asked Questions

How to contact the author / maintainer of MJAI Server?

You can contact 9ns4esyx on Discord. However, Discord does not allow sending DMs between users that are not friends and do not have mutual servers. Please follow the instructions below to ensure smooth communications.

First, you should join the Discord server MJAI Server by this link: https://discord.gg/BDE95aXs5r. When accepting invitation, please make sure that you allow DMs from other members in this server. (You can also enable this in the server privacy settings after joining the server.) Then, you should send a friend request to 9ns4esyx. The author will send you DMs without accepting the friend request, and then you can send DMs back too.

The reason that the author does not accept friend requests is to protect privacy of all users. Users communicating by DMs without being friends will not appear in the mutual friends lists of Discord profiles. The Discord server is configured to have no public channels, so that the list of members is not visible to people other than the server administrators.

How to register an account for MJAI Server?

You can register a normal account at the API endpoint /user/register. If the HTTP status code is not successful, it may be because the name you try to register has already been occupied, the server has disabled public registration, or the number of users allowed by public registration has exceeded the limit. The specific reason will be shown in the API response. If you really want to register an account when public registration is not available, you can contact 9ns4esyx on Discord; your registration may be approved depending on actual situations (server loads, etc.).

Alternatively, you can log in temporarily at the API endpoint /user/trial. The server will use your public IP address as the identifier, which means that all requests in the same session must be sent by the same public IP that requested temporary accounts. The trial code required is FREE_TRIAL_SPONSORED_BY_MJAPI_DiscordID_9ns4esyx. Similar to the normal user registration, there is also a limit of the number of active temporary users. The trial API will return an unsuccessful status code if the trial is disabled, the limit is exceeded, or there is already an active session of a temporary account using the same IP (which can be from another device sharing the same public IP).

How long will the sessions stay active without activities?

All sessions will be active for at least an hour after the last API request. The session tokens will be revoked shortly after the one-hour inactivity grace period, after which clients must log in again. If clients actively post requests to /user/logout, the session tokens will be revoked immediately.

How long is the guaranteed access of temporary accounts?

Temporary IP-based accounts are guaranteed access for 24 hours after their first requests at /user/trial. After 24 hours, if there are new temporary account requests from other IP exceeding the quota, this IP may be forced to log out. If there are no excessive temporary account requests from other IP, this IP can have continued access, and after another 24 hours, it will get guaranteed access for next 24 hours again. The guaranteed access period (ttl) and grace period until the next possible grant (grace) can be obtained at /user.

How can I regain access of temporary accounts after losing the session tokens requested?

If you requested a session token at /user/trial but accidentally lost it, you have no way to request a new session token using the same IP in an hour. You need to wait until the previous session expires, and then you can request trial again.

Can I recover my account if I lose / forget my username and/or secret?

If you do not know your username, there is no way to recover your account.

If you lose your secret somehow but still remember your username, you can contact 9ns4esyx on Discord if you requested an account by Discord. You will be given a new secret if the old one is nowhere to find. Otherwise, if you registered your account by yourself (such as by the API endpoint /user/register), your account can only be recovered if you can prove ownership of it. For example, you use your email address as the username, and you are able to receive a verification email. You will be given a new secret; the old one cannot be retrieved because only hash values of secrets (with salts) are stored in the database.

How can I get a new secret if my current secret is leaked?

If you suspect that your current secret is leaked, such as other people using your Mjai quota or your sessions being revoked for no reasons (probably because of another program trying to log in when your sessions are still active), you can contact 9ns4esyx on Discord. You will get a new secret if you can prove ownership of your account, and the old secret will become invalid.

What models can I access?

You can see the list of all models (models) and the ones you can access (permit) at /mjai/list. Normal users will have access to a subset of all models, while temporary users will have a much smaller subset.

What is the request rate limit?

For critical API endpoints, besides requiring authentication by session tokens, they have a rate limit. The soft limit is 1 HTTP request per second, and the hard limit is 2 HTTP requests per second. If the soft limit is exceeded, the processing of requests that are too fast will be delayed to meet the soft limit. If the hard limit is exceeded, the excessive requests will receive the HTTP status code 429 Too Many Requests immediately, and these requests will not be processed.

What is the maximum request body size?

The maximum body size for each request is 4 KB (4096 bytes). If any request has a body size exceeding this limit, the server will return the HTTP status code 413 Payload Too Large.

For almost all API endpoints, this limit is much more than enough. The exception is the API endpoint /mjai/batch, because multiple Mjai events can be sent together in a single request. Usually, the serialized event batch in the request body will have a size much smaller than 4 KB (if JSON serialization is compact and there are no redundant fields), given that the number of Mjai events between action queries is usually around 8. However, if clients start querying in the middle of a kyoku (which can be a result of reconnection after disconnected, restart after errors, or special usage), the number of Mjai events since the start of the kyoku may be too large to fit in a single request. Clients should split these events into multiple batches to prevent exceeding the request body size limit. A safe batch size is 32, if there is at most one start_kyoku event per batch. (Clients never need to include two or more start_kyoku events in the same batch, because the latest start_kyoku event will reset the game states, making all previous events useless.) Of course, the batch size can probably be larger, especially when there is not a start_kyoku event in the batch. Clients can decide more precise upper bounds by calculating or estimating the final sizes after serialization, but 32 is already enough for most use cases, since the number of batches is at most around 5 even if approaching the end of the current kyoku.

What is the Mjai quota of API queries?

You can query the API endpoint /mjai/limit for the number of Mjai events allowed every 24 hours. At /mjai/usage, you can see the current number of Mjai events used. The usage count will be reset at least 24 hours since the last reset, which will happen just before the first request that consumes Mjai quota after your account is eligible for resets.

Which endpoints consume Mjai quota?

The endpoints /mjai/start and /mjai/act consume 1 per request. The endpoint /mjai/batch consumes the number of events in the batch per request. If the request body format is not correct, each endpoint will still consume 1 per request. If the events are invalid (such as not compatible with the current game states), they will still consume the same numbers as valid ones.

How does the server handle invalid requests?

For request bodies that cannot be parsed, these requests are completely discarded and the game states will not be updated.

For request bodies that contain events incompatible with the current game states, only incompatible events are discarded. If the incompatible event is in the request to /mjai/act or the one with the latest seq in the batch of events sent to /mjai/batch, an error will be returned. To send correct events after incompatible ones, you need to use new seq numbers, because the incompatible events have been correctly parsed and occupied the corresponding seq. Sometimes, it is impossible to recover because some events after the incompatible ones are accepted and update the game states. It can happen because these events do not directly conflict with the game states, but they can corrupt the game states because there are intermediate events missing, which results in incorrect update orders. In this case, you need to resend all correct events since the start of the current kyoku including the start_kyoku event (and optionally request /mjai/start before this, if you mess up seq).

Notice that if you are using the API endpoint /mjai/batch, only the error corresponding to the last event (with the latest seq) will be returned, which may not be the cause of errors. Thus, it is advised that you debug your programs using /mjai/act during development.

How to get dahai decisions corresponding to reach without actually declaring riichi?

The server can tolerate reach events without corresponding reach_accepted events. If reach_accepted events do not appear after dahai, the server will revert the state as if there have been no reach events. At the next turn, clients can send reach events to get dahai decisions again without corrupting the game states, and the server will not return errors. Developers will not need to force users to declare riichi or resend all events since the start of kyoku.

Why do Mjai endpoints return errors?

Every error has a corresponding error message to which you can refer to understand the specific reasons.

If the error message is operation not permitted, the HTTP status code can explain the reason: if 401, it means that your session token is missing or expired; if 403, it means that you do not have a high enough user permission to use the current endpoint. Another possible error message is mjai query limit exceeded, which means that you do not have enough Mjai quota left for the server to process the current request.

For /mjai/start, errors can happen if you supply an invalid player ID (negative, larger than 3 for 4-player models, or larger than 2 for 3-player models), a negative or too large bound, a non-existent model, or a model that you do not have a high enough user level or permission to access.

For /mjai/act and /mjai/batch, errors are likely results of kyoku not properly initialized (missing or invalid start_kyoku events) or events incompatible with the current game states. For incompatible events, the error messages will explain how they conflict with mahjong logic.

Incompatible events can be because of bugs in clients or different game rules. All AI models of MJAI Server target the standard rules of Tenhou (南喰赤), which means hanchan games, kuitan, and akadora (one red five for each numbered suit). Minor rule difference may not affect much, except for suboptimal performance in corner cases, but if the rules differ a lot, conflicts are expected to happen. If you encounter conflicts because of difference in rules, you can try to implement rule-based guards in clients if possible. Otherwise, MJAI Server cannot handle your use cases, and you will need to use another service or AI model for your purposes.

Does MJAI Server record any user or game information?

MJAI Server requires some user and game information in a short-term session to function. User information includes usernames and user IDs on MJAI Server, public IP addresses, and timestamps of API accesses. Game information includes requested models, player IDs (from 0 to 3 for 4-player or 2 for 3-player), game states of the current kyoku, and last bot actions. After users actively log out or sessions expire, all information is discarded except timestamps of API accesses with user IDs on MJAI Server (to enforce rate limits; temporary users will have their public IP addresses retained in memory only because they are the only identifiers).

Notice that MJAI Server has no knowledge of how you use the service. It never records any player names even if they are given in the start_game events. The hora and ryukyoku events are ignored, so it is not aware of the game results either. All session information is kept in memory, which is completely gone after sessions are revoked. Only usernames, user IDs, user permissions, user levels, and user secrets of MJAI Server are stored on persistent storage. MJAI Server uses strong hash functions with salts to store user secrets, so that they cannot be figured out even if the database leaks somehow.

How to get more Mjai quota / access models that require higher user levels?

MJAI Server provides special access only to research study users. If you have formal research study projects, you may contact 9ns4esyx on Discord. The Mjai quota can be increased and higher user levels may be granted, depending on the situations.

The author is also considering accepting donations / tips to cover model training and server costs. However, methods to donate / tip will only be available after some non-trivial number of people have expressed the willingness to do so. Users are expected to have access to all models and a significant quota boost with active donations / tips.