JetBrains Space Help

Receive Payload from Space

With some types of applications, Space acts as a client – it sends POST requests to the application endpoint with JSON payload inside. For example, when a user types in the application chat channel, Space sends payload containing the user input; if the application is subscribed to webhook notifications, Space sends payload with event details, and so on.

Payload contents

The payload consists of the name of a payload class, class-specific payload data, and data that is common for all payload types (like Space URL, user ID, and so on).

For example, this is a sample payload from Space when a user sends help command to a chatbot:

{ // [[[Payload class|#payload-classes]]] "className": "MessagePayload", // Class-specific payload data "message": { "messageId": "CsT000CsT", "channelId": "3FhQeS2URbeY", "messageData": null, "body": { "className": "ChatMessage.Text", "text": "help " }, "attachments": null, "externalId": null, "createdTime": "2021-05-21T17:01:33.767Z" }, // [[[Common payload data|#common-payload-data]]] "accessToken": "", "verificationToken": "abc1234", "userId": "1mEGCd1FvoAh", "serverUrl": "https://mycompany.jetbrains.space", "clientId": "2ulA3W2Vltg6", "orgId": "8fd4d79a-d164-4a71-839a-ff8f8bcd6beb" }

Payload types

To help you process different kinds of payload, Space SDK provides a number of classes. All these classes implement the ApplicationPayload interface.

Class

Description

Relevant for

AppPublicationCheckPayload

JetBrains Marketplace sends this payload during application verification.

Multi-org applications distributed through JetBrains Marketplace.

InitPayload

Initializes the application that was installed from JetBrains Marketplace.

Multi-org applications distributed via links or through JetBrains Marketplace.

ListCommandsPayload

Requests a list of available commands. Space sends this payload type when a user types slash / or another character in the application chat channel. The application must respond with a JSON list of commands.

Chatbots, slash commands.

MenuActionPayload

Contains info about the custom menu item selected by a user.

Applications that extend Space context menus with custom items.

MessagePayload

Contains a message sent by a user to the application from a chat channel.

Chatbots, slash commands.

MessageActionPayload

Contains info about the action executed by a user in the application chat channel. Typically, this is a result of user interaction with a UI control in a chat message, for example, clicking a button.

Chatbots, slash commands.

WebhookRequestPayload

Contains info about the event occurred in Space. The application must be subscribed to this event with a corresponding webhook.

Applications that use webhooks to receive notifications about Space events.

Reading the payload

To help you handle the payload, Space SDK provides the Space helper object. This is how you can use it to process the payload depending on its type. For example, in a Ktor application:

@file:OptIn(ExperimentalSpaceSdkApi::class) package com.example import io.ktor.application.* import io.ktor.http.* import io.ktor.request.* import io.ktor.response.* import io.ktor.routing.* import space.jetbrains.api.ExperimentalSpaceSdkApi import space.jetbrains.api.runtime.Space import space.jetbrains.api.runtime.helpers.RequestAdapter import space.jetbrains.api.runtime.helpers.SpaceHttpResponse import space.jetbrains.api.runtime.helpers.processPayload import space.jetbrains.api.runtime.ktorClientForSpace import space.jetbrains.api.runtime.types.InitPayload import space.jetbrains.api.runtime.types.MenuActionPayload import space.jetbrains.api.runtime.types.RefreshTokenPayload import space.jetbrains.api.runtime.SpaceAppInstance import space.jetbrains.api.runtime.helpers.SpaceAppInstanceStorage // we use in-memory storage for storing Space instances // in real life, use a persistent storage, e.g., a database val spaceInstances = HashMap<String, SpaceAppInstance>() object AppInstanceStorage : SpaceAppInstanceStorage { override suspend fun loadAppInstance(clientId: String): SpaceAppInstance? { return spaceInstances[clientId] } override suspend fun saveAppInstance(appInstance: SpaceAppInstance) { spaceInstances[appInstance.clientId] = appInstance } } val ktorClient = ktorClientForSpace() class KtorRequestAdapter(private val call: ApplicationCall) : RequestAdapter { override suspend fun receiveText() = call.receiveText() override fun getHeader(headerName: String) = call.request.headers[headerName] override suspend fun respond(httpStatusCode: Int, body: String) { call.respond(HttpStatusCode.fromValue(httpStatusCode), body) } } fun Routing.routes() { post("api/myapp") { Space.processPayload(KtorRequestAdapter(call), ktorClient, AppInstanceStorage) { payload -> // analyze payload type when (payload) { is InitPayload -> { // initialize the app... SpaceHttpResponse.RespondWithOk } is MenuActionPayload -> { // react to menu item click // val result = ... SpaceHttpResponse.RespondWithResult(result) } is RefreshTokenPayload -> { // save refresh token... SpaceHttpResponse.RespondWithOk } else -> { SpaceHttpResponse.RespondWithOk } } } } }

In a more generic approach, you can use only the readPayload(body: String): ApplicationPayload SDK helper function to handle payload:

fun main() { embeddedServer(Netty, port = 8080) { routing { post("/api/from-space") { val body = call.receiveText() val payload = readPayload(body) // analyze payload type when (payload) { is MessagePayload -> { println("This is MessagePayload") call.respond(HttpStatusCode.OK, "") } else -> call.respond(HttpStatusCode.BadRequest, "Unsupported payload type") } } } }.start(wait = true) }

Common payload data

Regardless of the type, the payload that comes from Space always contains some common information: user ID, server URL, and other. To help you get this data, Space SDK provides a number of extension methods for the ApplicationPayload interface.

val payload = readPayload(body) // ID of a user who initiated the request // Not available for the payload types that // do not imply user interaction val userId = payload.userId // Client ID issued to the app // during the [[[app registration|https://www.jetbrains.com/help/space/register-app-in-space.html]]] val clientId = payload.clientId // URL of your Space instance val url = payload.serverUrl // ID of your organization in Space val orgId = payload.orgId // Verification token // used to [[[verify Space in the app|https://www.jetbrains.com/help/space/verify-requests-from-space.html]]] // null if you choose other verification way val token = payload.verificationToken
Last modified: 25 November 2022