Skip to main content
Publish event info to your own website

Using the push feed

Updated over a month ago

You can publish event info to external websites. This allows you to update your own website with info from Stager. The event info contains text, images and video, but also location, times and ticket sales info. This article shows you the technical details to link the Stager feed to a website.


Create a publication channel

Go to Settings - Integrations - My publication channels. To create a new channel, click the '+ New publication channel' button. Here you can enter relevant information about your new channel.

Make sure the channel has a name. Indicate which permissions a publication channel receives. There are two options:

  • Limited: All event information entered in the Publicity tab, plus basic ticketing info, such as which tickets are for sale (and their current status determined by Stager) and how much the tickets cost.

  • Extended: All event information as entered in Publicity plus the project type, all ticketing info (including sold, reserved and available ticket counts per ticket group, allowing you to decide what status you show) and which link members should use.

Enter a webhook URL and an email address of the person or company creating this link. It allows Stager to communicate technical details to the the right people.

After clicking save, you will be taken to the publication channel overview page. There, you will see three blocks - the general information that you just entered, together with a new push feed block and a legacy feed block.

The push feed block allows you to fully synchronise all of the data published to this channel. This block also displays the last error that we have received back from the endpoint to help you troubleshoot any issues.

The legacy block simply displays your token to use this channel together with the legacy pull feed. Read more about this here. This feed is considered deprecated and will be removed in the future, so make sure not to build anything new on top if it.


Publish information

Go to an event in your calendar and open the Publicity tab. Here you enter event info. Scroll to the bottom and check the box with the correct publication channel. You'll see the name of the channel under 'My publication channels'. Make sure to publish or schedule to publish the info to the correct channel.


Technical explanation for your website developer

The Stager feed is a push-feed implemented using a webhook which users can specify. Changes in the event trigger a push to your webhook providing you with updated event data. You first need an endpoint on your own website that we can push all information to. To help you, the push feed comes with it's own documentation:

You can see a single web hook, together with 6 different possible JSON schemas. These schemas are the different messages that we push to your endpoint. They are always combined with a relevant message type string. The OrganizationSync messageContent, for example, is always combined with the ORGANIZATION_SYNC messageType . Because of this, it is recommended to first parse the messageType in your integration, and then properly deserialize the messageContent.

We also recommend implementing a queue mechanism to make sure that your endpoint can handle busy moments (such as peak sales, where many messages can be sent in a short timespan) and large messages (such as the nightly sync). This would make sure the contents of the message are processed outside of the request cycle, and thus do not hold up any subsequent requests or cause time-outs.

In the publication channel overview page, you will see a testing block. This has a handful of important fields. First, there is an authentication token. This is quite important by itself, and is explained further down in this article. Under that, you can see a 'Send all data' button. Use this to test you integration an to sync your baseline data (everything published at the time).

Next, you can see a "View logs" button. Clicking it will take you to a week long (split up by day) request log of the selected channel. Each log entry can be opened to see the request information, response (if received) and of course the payload. Last but not least, we have the last error field, which displays the last encountered error. This acts similarly to the log without you having to comb through it to find errors.


Verification

As data provided by the Stager Push Feed will most likely be used to display your Stager events and any related content directly on your website, we recommend you set up your application to verify that incoming data is sent by Stager and not a different party. This makes sure that no 'fake' data gets through to your website, preventing in from being defaced.

To help you with this, Stager will sign all outgoing requests to your application with an X-Signature HTTP header. This signature is created using the full body of the request sent to your endpoint. It uses the HMAC-SHA256 hashing algorithm and the authentication token of your channel as the secret key.

You can easily verify the signature using the request body, the authentication token of your channel, the signature itself (the value of the X-Signature header) and any cryptography library available within your chosen tech stack that has support for the HMAC-SHA256 algorithm.

Verification code samples

We have a limited list of code samples to guide you through verifying requests received at your Stager webhook endpoint. If you use something we don't have on this list, feel free to reach out - we can either try and point you in the right direction or update the list based on your implementation.

Node.js / Express

import express from "express";
import bodyParser from "body-parser";
import crypto from "crypto";

const HMAC_ALGORITHM = "sha256";
const HMAC_ENCODING = "hex";

// The authenticity token, found on the selected channel page.
// Assumed that it is set as an enviroment variable,
// which is recommended, as the token is considered a secret.
const HMAC_SECRET = process.env.SECRET_TOKEN;

// Recommended as messages can get quite large
// (Especially the nightly full sync message)
app.use(bodyParser.json({ limit: "50mb" }));

// Webhook endpoint - receives push feed requests from Stager
app.post("/stager-feed", (req, res) => {
// Prepare required data
const body = req.body;
const bodyString = JSON.stringify(body);
const stagerSignature = req.header("X-Signature");

// Create Hmac object, generate control signature
hmacObject = crypto.createHmac(HMAC_ALGORITHM, HMAC_SECRET);
hmacObject.update(bodyString);
const controlSignature = hmacObject.digest(HMAC_ENCODING);

// Verify signature provided by Stager
if (stagerSignature === controlSignature) {
// Signature valid, message is safe to process

// ...

// Close connection with a 200 response
res.status(200).send("Request received and message processed!");
} else {
// Signature invalid, message ignored
// Close connection with a 401 response
res.status(401).send("Request validation failed!");
}
});

Kotlin / Play

package controllers

import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec
import org.apache.commons.codec.binary.Hex
import play.mvc.Controller
import play.mvc.NoAuthenticityToken
import play.mvc.results.Forbidden
import play.mvc.results.Ok
import play.mvc.results.Result

// The authentication token, found in the Stager Backstage
// Assumed that it is set as an environment variable
// named "authenticationToken"
// This is recommended, as the token is considered a secret
const val AUTHENTICATION_TOKEN_NAME = "authenticationToken"

const val HMAC_ALGORITHM = "HmacSHA256"
const val SIGNATURE_HEADER = "X-Signature"

class StagerFeedRequestHandler : Controller() {
@NoAuthenticityToken
fun handle(): Result {
val body = request.body
val bodyBytes = body.readAllBytes()

val headers = request.headers
val stagerSignature = headers[SIGNATURE_HEADER]?.value()

// Verify signature provided by Stager
return if (validateSignature(bodyBytes, stagerSignature)) {
// Signature valid, message is safe to process

// ...

Ok() // Close connection with a 200 response
} else {
// Signature invalid, message ignored
// Close connection with a 403 response
Forbidden("Request validation failed!")
}
}

private fun validateSignature(
body: ByteArray,
signature: String?
): Boolean {
// Check whether signature is present
return signature?.let { // Signature present, verify

// Construct SecretKeySpec object from the authentication token
val secretKeyEnvVar = System.getenv(AUTHENTICATION_TOKEN_NAME)
val secretKeyBytes = Hex.decodeHex(secretKeyEnvVar.toCharArray())
val secretKey = SecretKeySpec(secretKeyBytes, HMAC_ALGORITHM)

// Create and initiate the Mac instance
val hmacInstance = Mac.getInstance(HMAC_ALGORITHM)
hmacInstance.init(secretKey)

// Generate control signature and the Stager signature against it
val controlSignature = hmacInstance.doFinal(body)
return controlSignature.contentEquals(secretKeyBytes)
} ?: run {
false // Signature missing, default to invalid
}
}
}

Response

The push feed expect a 2XX response back within a specified time limit. For ORGANZIATION_SYNC, the time is 30 seconds. For all other messages, it is 10 seconds. If no response is received within this time, the connection is terminated and considered failed due to timeout. This is logged as an error both within Stager (to be handled internally) as well as the backstage (the "view logs" page and the last error block) for you to see.

Other responses are also allowed (for example, specific error messages such as 403 in case verification fails) to help aid debugging. These will be handled as errors though.


Push triggers

There are 3 different ways that the feed pushes messages to your endpoint:

  • Every night around 2AM CET a full sync message is pushed. This message contains all events connected to the channel together with their publication data, program items and ticket groups. This acts as a fallback in case other messages are missed, meaning that you will have up-to-date event and ticket information at least every night.

  • When an event has passed its publication time. Whenever an event passes it's publication time, it will automatically be pushed to all relevant channels.

  • When a relevant action occurs within Stager, be it caused by you or one of your customers/ticket buyers. There are a couple dozen places in Stager where you or a ticket buyer can affect your publishing data. In each of these cases, a message is sent. This message is always the smallest possible one from the 6 different types that can be sent.

The 6 different message types are triggered as follows:

  1. SYNC_ORGANIZATION

    1. Nightly sync, executed every night at around 2AM CET.

    2. 'Send all data' button, located in Settings - Integrations - My publication channels - Channel.

    3. 'Activate channel' button. Only available when a channel is inactive, located in Settings - Integrations - My publication channels - Channel.

  2. DELETE_ORGANIZATION

    1. When an organization is deleted (generally only relevant for aggregators).

    2. 'Deactivate channel' button. Only available when a channel is active, located in Settings - Integrations - My publication channels - Channel.

  3. UPDATE_EVENTS

    1. Whenever the publishing time of an event is reached.

    2. When an event is restored from the Trash Can (in Account - Trash Can - Events)

    3. Single events updates:

      1. Any edits made to the Main tab.

      2. Any edits made to an associated program item in the Program tab.

      3. Any edits made to the Publicity tab.

      4. Any edits made to the Tickets tab.

    4. Multiple event updates (all events connected to a particular entity):

      1. Any edits made to Locations and Spaces (in Settings - Planning).

      2. Any edits made to Event types (in Settings - Planning).

      3. Any edits made to Project types (in Settings - Planning).

      4. Any edits made to Event labels (in Settings - Marketing).

      5. Any edits made to Customer interests (in Settings - Marketing).

  4. DELETE_EVENTS

    1. Main tab exceptions:

      1. When the status of an event is changed from publishable (Confirmed, To be confirmed or Cancelled) to an unpublishable (Option) the DELETE_EVENT message is sent as the event is then considered deleted for the feed.

    2. Publicity tab exceptions:

      1. When a publicity channel is deselected from the list, the event is considered deleted from said channel, and this message is sent.

      2. When the publication status is changed to not (yet) published and the event had already been published previously, it is considered deleted from the feed and this message is sent.

    3. 'Delete event' button on the Main tab of an event (in case of cancelling, the previously mentioned exception counts).

  5. UPDATE_TICKET_GROUPS

    1. Single ticket group updated in the details on the Tickets tab.

    2. Order paid and completed:

      1. In the online ticket shop, after getting through the payment flow.

      2. On the door sales screen, after successful sale.

    3. Reservation cancelled/expired.

    4. Refund processed.

    5. Ticket type updated in Settings - Ticketing - Ticket types.

  6. DELETE_TICKET_GROUP

    1. Ticket group deleted from an event.

    2. Ticket type deleted with ticket groups connected to it.

Did this answer your question?