Thanks for checking out Grapevine.

Before continuing, you should create an account or sign in.

Game Configuration

Once you have an account, visit your configuration page. This will let you create a game on Grapevine. It will then show you your Client ID and Client Secret which will be used to authenticate against the Grapevine network.

Channels

You also subscribe to the channels you want your game to pay attention to. Right now Grapevine has the following public channels:

  • gossip
  • testing
  • moo

In addition to those listed above, you can subscribe to any valid channel name. This will dynamically create channels as you subscribe to them. They will exist for anyone to connect to, but not show on the website until the admins approve them.

A valid channel name must be between 3 and 15 characters (inclusive), letters (a-zA-Z), _, and - only.

You will only receive messages for channels you are subscribed to.

Language

Many games connect to Grapevine's chat, and all of them have varying levels of allowed chat.

Grapevine channels may contain adult language, so consider making your implementation of cross-chat opt-in.

While adult language is allowed, offensive language is not. Please read our Code of Conduct for more information.

Server Support

The following servers/frameworks have built-in support or a library to import for Grapevine support:

Connecting

Once you have your Client ID and Client Secret, you can start connecting to the Grapevine network. Point your websocket client at:

wss://grapevine.haus/socket

Once you are connected, you must send an authenticate message to authenticate your connection.

Expectations of a Connecting Game

If you are connecting to the Grapevine network, please know that you connect under the following assumptions:

  1. Grapevine will go down sometime while you are connected. Most likely for a new deploy. Make sure your game does not crash because of this.
  2. While Grapevine is down, your app should transition channels to local only.
  3. Similarly, you should reconnect back to Grapevine when it comes back online.
  4. You must support UTF-8 at the server level. Several connected games allow UTF-8 input so you may receive it at any time.

It is suggested to follow these:

  1. Formatting for player names should be in the format of Player@GameName.

Common Vocabulary

  • ref is a unique reference that identifies an event in a request and response. This should be a UUID.
  • channel is the name of a channel on Grapevine.
  • game is the short name of a connected game.
  • name is the name of a player in a connected game.

Socket Error Codes

4000
Authentication failed
4001
Heartbeat failure

Core Events (channels)

Since 1.0.0

These are the core features of connecting to Grapevine. These include authenticating, a heartbeat, basic public channels.

authenticate

Since 1.0.0

This event authorizes the connection and afterwards you will start to receive new broadcasts.

{
  "event": "authenticate",
  "payload": {
    "client_id": "client id",
    "client_secret": "client secret",
    "supports": ["channels"],
    "channels": ["grapevine"],
    "version": "1.0.0",
    "user_agent": "ExVenture 0.23.0"
  }
}
  • supports is required. This is an array of features the connecting game supports. It must contain at least channels. Extra unknown options will result in the socket being disconnected.
  • channels is optional. This is an array of channels you wish to subscribe to on start. See the list of channels for available channels you can subscribe to.
  • user_agent is optional but suggested.
  • version is optional but suggested. This is highest version number that you as a client know of. As Grapevine updates, it will be able to alert you that there are new features available. If not present, then a default of 1.0.0 is used.

You will receive a response from this with a sucess or failure message.

{
  "event": "authenticate",
  "status": "success"
  "payload": {
    "unicode": "✔️",
    "version": "2.3.0"
  }
}
  • unicode is present to ensure you properly parse unicode characters.
  • version is the current version of Grapevine.

If you attempt to subscribe to bad channels, you may receive a failed subscribe message. See more above about valid channel names.


heartbeat

Since 1.0.0

Once you are authenticated, the server will start sending heartbeat events.

{
  "event": "heartbeat",
}

When you receive a heartbeat, you must respond to it with a heartbeat of your own.

{
  "event": "heartbeat",
  "payload": {
    "players": ["player"]
  }
}
  • players is optional but suggested. You should include your full player list to keep Grapevine in sync with you. Grapevine must know your players are online to forward remote tells.

NOTE: If you do not respond to these heartbeats the socket will be closed after three failed beats.


restart

When Grapevine knows a restart is imminent, you will receive this event. This event will be sent before a server restart due to a deploy.

After receiving this event, your connection to Grapevine may drop at any moment.

{
  "event": "restart",
  "ref": "f15ed228-ad43-4af4-9466-7d353fc9bf11",
  "payload": {
    "downtime": 15
  }
}
  • downtime is a suggested amount of seconds you should wait before restarting. It is a hint from the server for how long it thinks Grapevine will be down.

channels/subscribe

Since 1.0.0

Subscribe to a new channel on your currently connected socket.

{
  "event": "channels/subscribe",
  "ref": "a6f8006d-ddac-465e-a3df-fb440e83189b",
  "payload": {
    "channel": "grapevine"
  }
}
  • ref is optional.
  • channel is required.

If a ref is included then you will get a response back confirming your message.

{
  "event": "channels/subscribe",
  "ref": "a6f8006d-ddac-465e-a3df-fb440e83189b"
}

You may receive a response to this as a failure, channel names are validated. See more above about valid channel names.

{
  "event": "channels/subscribe",
  "ref": "a6f8006d-ddac-465e-a3df-fb440e83189b",
  "status": "failure",
  "error": "Could not subscribe to 'bad channel name'",
}

channels/unsubscribe

Since 1.0.0

Unsubscribe to a channel you are subscribed to.

{
  "event": "channels/unsubscribe",
  "ref": "e4d07334-4a4b-44ba-94dc-2b937160a466",
  "payload": {
    "channel": "grapevine"
  }
}
  • ref is optional.
  • channel is required.

If a ref is included then you will get a response back confirming your message.

{
  "event": "channels/unsubscribe",
  "ref": "e4d07334-4a4b-44ba-94dc-2b937160a466"
}

channels/broadcast

Since 1.0.0

When a channel you are subscribed to receives a new message you will get a broadcast.

{
  "event": "channels/broadcast",
  "ref": "89036074-446f-41ab-b87a-44ef1f962f2e",
  "payload": {
    "channel": "grapevine",
    "message": "Hello everyone!",
    "game": "ExVenture",
    "name": "Player"
  }
}

channels/send

Since 1.0.0

To send a new message, use this event.

The message in the payload will have MXP tags stripped before broadcasting. Do not send MXP data.

You will not get a channels/broadcast event for messages you send.

{
  "event": "channels/send",
  "ref": "28523394-6dcf-4c2a-ad1d-2d0ef8bb823b",
  "payload": {
    "channel": "grapevine",
    "name": "Player",
    "message": "Hello everyone!"
  }
}
  • ref is olitional.
  • channel is required. channel must be a channel you are subscribed to.
  • name is required.
  • message is required.
  • See Common Vocabulary for payload data.

If a ref is included then you will get a response back confirming your message.

{
  "event": "channels/send",
  "ref": "28523394-6dcf-4c2a-ad1d-2d0ef8bb823b",
}

Player Events (players)

Since 1.0.0

These events are related to the players support flag. Add this to your supports array when connecting.

players/sign-in

Since 1.0.0

When a player signs into your game, send this message. It will broadcast to other games and also update Grapevine's tracking of who is signed in.

You will not receive a players/sign-in event back for messages you send.

{
  "event": "players/sign-in",
  "ref": "0e11c053-65b3-477c-aae9-5cd8cf21dc8f",
  "payload": {
    "name": "Player"
  }
}

If a ref is included then you will get a response back confirming your message.

{
  "event": "players/sign-in",
  "ref": "0e11c053-65b3-477c-aae9-5cd8cf21dc8f"
}

While connected with the players flag, you may receive an update from another game. You may wish to broadcast to your local players that someone has come online in the network.

{
  "event": "players/sign-in",
  "payload": {
    "game": "ExVenture",
    "name": "Player"
  }
}

See Common Vocabulary for information on payload data.

Note: you must still respond to heartbeats with your full list. Each beat fully replaces the list ensuring it keeps in sync. This is for between the beats and notifying connected games.


players/sign-out

Since 1.0.0

When a player signs out of your game, send this message. It will broadcast to other games and also update Grapevine's tracking of who is signed in.

You will not receive a players/sign-out event back for messages you send.

{
  "event": "players/sign-out",
  "ref": "da4c5503-dd15-490a-9d0d-85e2c50b72de",
  "payload": {
    "name": "Player"
  }
}

If a ref is included then you will get a response back confirming your message.

{
  "event": "players/sign-out",
  "ref": "da4c5503-dd15-490a-9d0d-85e2c50b72de"
}

While connected with the players flag, you may receive an update from another game. You may wish to broadcast to your local players that someone has gone offline in the network.

{
  "event": "players/sign-out",
  "payload": {
    "game": "ExVenture",
    "name": "Player"
  }
}

See Common Vocabulary for information on payload data.

Note: you must still respond to heartbeats with your full list. Each beat fully replaces the list ensuring it keeps in sync. This is for between the beats and notifying connected games.


players/status

Since 1.1.0

To check the status of other players on the network, send a players/status event.

{
  "event": "players/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4"
}

ref is required.

In response you will receive a message per connected game.

{
  "event": "players/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4",
  "payload": {
     "game": "ExVenture",
     "players: ["admin"]
  }
}
  • players is the list of players that are currently online.
  • See Common Vocabulary for payload data.
Single Game Update

You can request an update to a single game by adding its name in the payload.

{
  "event": "games/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4",
  "payload": {
    "game": "ExVenture"
  }
}

You will only receive an update for that game. It will look the same as above.


Tell Events (tells)

Since 2.0.0

These events are related to the tells support flag. Add this to your supports array when connecting.

It is suggested to also support the players flag, as you can keep your players' status more up to date on Grapevine. Players must be online on Grapevine to receive tells.

tells/send

Since 2.0.0

{
  "event": "tells/send",
  "ref": "5c528fc3-cb9e-4867-98ea-6e235594241e",
  "payload": {
    "from_name": "Player",
    "to_game": "ExVenture",
    "to_name": "eric",
    "sent_at": "2018-07-17T13:12:28Z",
    "message": "hi"
  }
}
  • ref is required.
  • from_name is required. This is the name of the player sending the tell.
  • to_game is required. This is the name of the game that will process the tell. The server will match this case insensitive against connected games.
  • to_name is required. This is the name of the receiving player.
  • sent_at is required. This is an ISO8601 formatted timestamp of when the message was sent. It must be in UTC, use the Z format for UTC.
  • message is required. This is the body of the tell.

If the game and player are online, you will receive a response back.

{
  "event": "tells/send",
  "ref": "5c528fc3-cb9e-4867-98ea-6e235594241e",
  "status": "success"
}

If the tell did not succeed in sending, you will receive an error response.

{
  "event": "tells/send",
  "ref": "5c528fc3-cb9e-4867-98ea-6e235594241e",
  "status": "failure",
  "error": "game offline"
}

Possible failure responses are:

  • game offline
  • sending player offline
  • receiving player offline
  • not supported, the connected game does not support tells

tells/receive

Since 2.0.0

When another game sends a tell to your game, you will receive this event.

{
  "event": "tells/receive",
  "ref": "d4a08749-acbe-45ab-bc0f-51609fd6b95b",
  "payload": {
    "from_game": "AMud",
    "from_name": "Player",
    "to_name": "eric",
    "sent_at": "2018-07-17T13:12:28Z",
    "message": "hi"
  }
}
  • from_name is the name of the player sending the tell.
  • from_game is the name of the game sending the tell.
  • to_name is the name of the receiving player.
  • sent_at is an ISO8601 formatted timestamp of when the message was sent. It is in UTC.
  • message is the body of the tell.

Game Events (games)

Since 2.1.0

These events are related to the games support flag. Add this to your supports array when connecting.


games/connect

Since 2.2.0

While connected with the games flag, you may receive a connection notice for another game. You may wish to broadcast to your local players that game has come online from the network.

{
  "event": "games/connect",
  "payload": {
    "game": "ExVenture",
  }
}

See Common Vocabulary for information on payload data.


games/disconnect

Since 2.2.0

While connected with the games flag, you may receive a disconnection notice for another game. You may wish to broadcast to your local players that game has gone offline from the network.

{
  "event": "games/disconnect",
  "payload": {
    "game": "ExVenture",
  }
}

See Common Vocabulary for information on payload data.


games/status

Since 2.1.0

To check the status of other games on the network, send a games/status event.

{
  "event": "games/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4"
}

ref is required.

In response you will receive a message per connected game.

{
  "event": "games/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4",
  "status": "success",
  "payload": {
    "game": "ExVenture",
    "display_name": "An ExVenture game",
    "description": "...",
    "homepage_url": "https://...",
    "user_agent": "ExVenture 0.26.0",
    "user_agent_repo_url": "https://...",
    "connections": [
      {"type": "telnet", "host": "example.com", "port": 4000},
      {"type": "web", "url": "https://example.com/play"}
    ],
    "supports": ["channels", "players", "tells", "games"],
    "channels": ["gossip"],
    "players_online_count": 3
  }
}
  • display_name is a less restrictive name for the game.
  • description is text about the game.
  • homepage_url is the home page for the game.
  • user_agent is the reported user agent of the connectin game. May not be present.
  • user_agent_repo_url is a source code repository for the user agent. May not be present.
  • connections is an array of connection objects. See below for more about connections. May not be present
  • supports if the game is currently connected, this is an array of what the socket supports. May not be present.
  • channels if the game is currently connected, this is an array of what channels the game is listening to. May not be present.
  • players_online_count if the game is currently connected, the number of players that are online. May not be present.
  • See Common Vocabulary for payload data.
Connection Object

A connection object contains ways of connecting to play the game.

Current connection types are: web, telnet, and secure telnet.

web
This is a web based game.
{
  "type": "web",
  "url": "https://example.com/play"
}
  • type is set to "web"
  • url is a web page to start playing the game.
telnet
This is a standard telnet connection.
{
  "type": "telnet",
  "host": "example.com"
  "port": 4000
}
  • type is set to "telnet"
  • host is the host name to connect to.
  • port is the port to connect to.
secure telnet
This is a TLS secured telnet connection.
{
  "type": "secure telnet",
  "host": "example.com"
  "port": 4000
}
  • type is set to "telnet"
  • host is the host name to connect to.
  • port is the port to connect to.
Query for a Single Game

You can request an update to a single game by adding its name in the payload.

You can also query for games not connected via this event.

{
  "event": "games/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4",
  "payload": {
    "game": "ExVenture"
  }
}

When requesting a single game, you might receive an error response. If the game is unknown.

{
  "event": "games/status",
  "ref": "c8cbaef2-b6e9-4110-b712-a312aee9e7d4",
  "status": "failure",
  "error": "unknown game"
}

You will only receive an update for that game. It will look the same as above.

Achievement Events (achievements)

Since 2.3.0

These events are related to the achievements support flag. Add this to your supports array when connecting.


achievements/sync

Since 2.3.0

You can request a series of events that send all of the achievements that the connecting game has.

{
  "event": "achievements/sync",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90"
}
  • ref is required.

The events you will get will look similar to this. You will receive an set of events that each contain at most 10 achievements. Each event will contain the total number of achievements for the ref. This way you can know when the full list has been sent.

{
  "event": "achievements/sync",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  "payload": {
    "total": 15,
    "achievements": [
      {
        "key": "ea7fb436-a99e-4e78-ad10-46acc6fb6912",
        "title": "Level Up!",
        "description": "You leveled up to level 10!",
        "points": 10,
        "display": true,
        "partial_progress": false,
        "total_progress": null,
      }
    ]
  }
}
  • total is the total number of achievements.
  • achievements is an array of achievements. See below for their properties.

The achievement attributes match the same attributes you would enter in from the Grapevine website itself.

  • key is an ID you will use in other events, read only.
  • title is a string.
  • description is a string.
  • points is an integer.
  • display is a boolean, if false the achievement will be "blurred" out on Grapevine until unlocked.
  • partial_progress is a boolean, if true total_progress must be provided.
  • total_progress is an integer.

achievements/create

Since 2.3.0

You can create new achievements with this event.

{
  "event": "achievements/create",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90"
  "payload": {
    "title": "Level Up!",
    "points": 10
  }
}
  • ref is required.

The payload should contain all of the attributes of an achievement that you wish to set. See achievement attributes above for more explanation.

You will receive a response with the key and full attributes of the achievement.

{
  "event": "achievements/create",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  "status": "success",
  "payload": {
    "key": "ea7fb436-a99e-4e78-ad10-46acc6fb6912",
    "title": "Level Up!",
    "description": "You leveled up to level 10!",
    "points": 10,
    "display": true,
    "partial_progress": false,
    "total_progress": null,
  }
}

You may receive an errors response, if there are errors.

{
  "event": "achievements/update",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  "status": "failure",
  "payload": {
    "errors": {
      "title": ["can't be blank"]
    }
  }
}

achievements/update

Since 2.3.0

You can update achievements with this event.

{
  "event": "achievements/create",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90"
  "payload": {
    "key": "ea7fb436-a99e-4e78-ad10-46acc6fb6912",
    "title": "Leveled Up!",
    "points": 15
  }
}
  • ref is required.

The payload should contain all of the attributes of an achievement that you wish to update. See achievement attributes above for more explanation.

You will receive a response with the key and full attributes of the achievement.

{
  "event": "achievements/update",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  "status": "success",
  "payload": {
    "key": "ea7fb436-a99e-4e78-ad10-46acc6fb6912",
    "title": "Leveled Up!",
    "description": "You leveled up to level 10!",
    "points": 15,
    "display": true,
    "partial_progress": false,
    "total_progress": null,
  }
}

You may receive an errors response, if there are errors.

{
  "event": "achievements/update",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  "status": "failure",
  "payload": {
    "errors": {
      "title": ["can't be blank"]
    }
  }
}

achievements/delete

Since 2.3.0

You can delete achievements with this event.

{
  "event": "achievements/key",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90"
  "payload": {
    "key": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  }
}
  • ref is required.

You will receive a response with the key.

{
  "event": "achievements/delete",
  "ref": "1dfae6f6-c0a8-4da5-a1e3-3ba656880d90",
  "status": "success",
  "payload": {
    "key": "ea7fb436-a99e-4e78-ad10-46acc6fb6912"
  }
}

Grapevine Login

You can integrate a common login through Grapevine by using OAuth 2.0.

For more information on the OAuth 2.0 flow, please check out the spec at OAuth.net.

Grapevine only supports the Authorization Code Grant type.

Redirect URIs

Before starting your integration, make sure to setup your redirect URIs on Grapevine. For each game you are integrating, set all of the allowed redirect URIs from the "View" link on the Your Games page.

The redirect_uri must be a secure https URI or a localhost URI for development purposes.

Scopes

When authorizing against Grapevine, you must provide a set of scopes you wish to request from the user. Listed below are the available scopes.

  • profile gets basic profile information about the user, such as a UID and username
  • email can be added with profile to get the user's email address included in the user information response

Authorization

Authorize Route: https://grapevine.haus/oauth/authorize

When authorizing you must provide your client_id, any scope you want, a state to keep track of the request, your redirect_uri, and the response_type must be code

A sample request is listed below.

https://grapevine.haus/oauth/authorize?client_id=YOUR-CLIENT-ID
&scope=profile
&state=STATE
&redirect_uri=https%3A%2F%2Fexample.com%2Fauth%2Fgrapevine%2Fcallback
&response_type=code

Token Generation

Token Route: https://grapevine.haus/oauth/token

To generate an access token from the authorization code from above, POST to the /oauth/token endpoint.

Access tokens expire after 1 hour.

A sample request is listed below.

POST https://grapevine.haus/oauth/token?client_id=YOUR-CLIENT-ID
&code=CODE
&grant_type=authorization_code
&redirect_uri=https%3A%2F%2Fexample.com%2Fauth%2Fgrapevine%2Fcallback

Fetching User Information

User Information Route: https://grapevine.haus/users/me

Once you have an access token for a user, you can fetch information about the user by doing a request to /users/me

The access token should be provided in the Authorization header as a Bearer token.

A sample request is below.

GET https://grapevine.haus/users/me
Authorization: Bearer my-token
Accept: application/json

200 OK
{
  "uid": "their UID",
  "username": "their username",
  "email": "their email"
}

Web Client

Grapevine allows you to turn on a web client for you game. You can do this from the settings for your game.

Once enabled you can adjust some settings for your game that will add gauges, see which players are currently signed in, and more.

Gauges

The web client can be configured to display gauges based on GMCP messages.

Each gauge requires the following information:

  • Name, display name for the gauge, example: "HP"
  • Package, GMCP package that needs to be enabled. This takes the format of Package[.SubPackage] VersionNumber, example "Char 1"
  • Message, this is the GMCP message that the gauge will use, example "Char.Vitals"
  • Value, path to field in the message that corresponds to the current value, example "hp"
  • Max, path to field in the message that corresponds to the max value, example "maxhp"
  • Color, color of the gauge
  • Docked, docked gauges are above the prompt, undocked gauges float in the top right

Each time a message is received that the gauge is configured for it will update the values in the gauge. Each message must contain both the value and the max value for the gauge to work.

Multiple gauges can be configured to use the same GMCP message. For instance, if you have HP and SP in the same message, you can configure both gauges to use this message.

Example message:

Char.Vitals {
  "hp": 10,
  "maxhp": 15,
  "sp": 12,
  "maxsp": 17
}