Webhooks

Note: Some of this article's information is redundant with our Template system which has more expansive features. See information on that system here: https://learn.battlemetrics.com/article/67-templates


About Webhooks

A webhook allows you to send a HTTP POST request from our server to yours. You can send a JSON or plain text request to a URL of your choosing. Webhooks are ideal when you want to be notified of a limited number of requests. A trigger is used to select the desired events and filter them down. A BattleMetrics webhook is created by adding the "Webhook" action to a trigger.

Webhooks are available to all users through the use of a personal trigger. Organization level use of webhooks requires the "Use Trigger Webhooks" permission.

The following options are available on the webhook action:

  • Name: A name to identify the webhook in activity logs
  • URL: The target of the webhook. The URL is only visible to users who have the permission to create/edit webhooks.
  • Shared Secret: The secret used to sign the request. The secret is set when the webhook is created and can not be retrieved afterwards. You new secret may be set later. A random secret will be generated using your browser's crypto API if available. See X-Signature below for additional information.
  • Content Type: The value for the Content-Type header presented to the receiving server. See Content-Type.
  • Logging: Request Logging level. See Logs.
  • Enabled: Enable or disable the webhook. The webhook may be automatically disabled under certain conditions. See Errors.
  • Body: The data sent with the webhook.

Recommendations

Any non-200 level response will be considered an error. We recommend that you return a 200 level response as quickly as possible and before you process the webhook data in any way. We use a 5 second timeout. Any response that takes longer than 5 seconds will be considered an error.

A queue to offload the work from the system processing requests may be necessary if you expect a large number of webhook requests or if you will be doing much processing.

There is no need to return any response other than a 200 level status code. The response will simply be ignored and discarded.

Alternatives

There are several alternatives to webhooks that may be better suited to whatever task you're trying to accomplish. See below for some examples:

API

The BattleMetrics API may be better choice when you want to maintain a copy of information for your own use. Either looking up the data on demand or periodically polling for the information may be used as an alternative, or supplement to webhooks. This could be a better choice when you do not require the information to be 100% up to date. The API is also capable of returning more information than webhooks and triggers have access to.

Websockets

The BattleMetrics website uses websockets to provide real time updates. All player and server updates that you would normally see on a server page are available. Activity messages are also broadcast over the same connection.

Websockets provide a better method for maintaining an accurate real time view of server activity than webhooks. We do not have documentation for using websockets yet, but we have provided a full example for streaming all data in TypeScript (JavaScript) suitable for browsers or Node.js. It is a stripped down version of what we use for the website. You can find the example pinned in our Discord in the #api channel.

Directly Querying the information

Depending on the information you want it could be better to go to the source. Server information such as player names and server details are easily requested directly from a server using any number of libraries that implement Source server queries.

Logs

Webhooks have three levels of logging. You may set logging to all, errors, or none. Logs allow you to see when requests were made, what status code we received and any errors we encountered.

  • None No requests or errors will be logged at all.
  • Errors All non 200 level responses and any other errors encountered will be logged.
  • All Successful requests will be logged in addition to any errors.

Requests

The following headers will be set on every request made by BattleMetrics.

Content-Type

Content-Type is set by the webhook action. Allowed values are application/json and text/plain .

X-Signature

All webhook requests made by BattleMetrics are signed using the shared secret set when the webhook was created. The signature can be found in the X-Signature header. The signature header looks like the following: t=1970-01-01T00:00:00.000Z,s=30d501ba7d4ff87be907e63c4ef520f179f6fcca45ecb5c6aa16a9c73e38bf79

The signature is a HMAC-SHA256 of the timestamp and request body separated by a period (. ). The timestamp will be in the ISO 8601 standard format.

Example

With a timestamp of 1970-01-01T00:00:00.000Z , a shared secret of fd38838ffca5116a9024b5957571e07bce98b207fe123f286f6af494ac8e6e54 , and body of Hello world the resulting X-Signature header would be: X-Signature: t=1970-01-01T00:00:00.000Z,s=4723360cfc233c2137ede9094bfb1b6d4b034d49a65bcb582acd725636ea6258

Date

The Date header is set to the time the trigger/webhook executed. The Date header is in the HTTP Date format per RFC 7231 requirements.

User-Agent

The User-Agent header is set to BattleMetrics-Webhook (+https://learn.battlemetrics.com/webhooks-ua) . The User-Agent header should not be relied on to identify requests made by us. This user agent could be used by anyone.

X-Request-ID

The X-Request-ID header is a UUIDv1 that is logged along with any errors we encounter on our end. Its only purpose is debugging.

Limits and Restrictions

There are several limits and restrictions placed on webhooks to help prevent abuse and limit any damage that could unintentionally be caused.

Rate limit

Both personal and organization webhooks are rate limited to 45 requests/second and 300 requests/minute. The rate limit is keyed to the user for personal triggers and to the organization for organization triggers.

Redirects

We will not follow redirects. You should either update the webhook to point to the correct URL, or forward the payload yourself.

429 Too Many Requests

If we receive a 429 Too Many Requests response we will stop sending webhooks. If there is a Retry-After we will wait the specified amount of time before we send any more webhooks. If there is no Retry-After value we will start with a delay of 2 seconds with an exponential backoff of up to 5 minutes.

If we encounter at least 50 errors and have not received a successful response from your server for 24 hours we will disable the webhook until it is manually enabled by you.

Errors

All non-200 status codes are treated as an error. Errors are handled much like 429 errors. After an error we will wait 2 seconds before sending any more requests with an exponential back-off of up to 5 minutes.

If we encounter at least 50 errors and have not received a successful response from your server for 24 hours we will disable the webhook until it is manually enabled by you.

Helpers

coalesce

The coalesce helper returns the first defined value and can be used to provide defaults.

  • {{coalesce player.ip.country player.steam.country "ZZ"}} -> Would return ZZ if both the country info for the player's IP and Steam profile were missing.
  • {{coalesce player.ip.country player.steam.country}} -> Would return undefined if both the country info for the player's IP and Steam profile were missing.

concatenate con·cat·e·nate verb link (things) together in a chain or series.

The concatenate helper will accept one or more values to be joined together and optionally a separator parameter.

  • {{concatenate player.name ": " msg.body}} -> Example Name: Hello world
  • {{concatenate player.name msg.body separator=": "}} -> Example Name: Hello world
  • {{concatenate player.id player.name player.steamID separator=", "}} -> 123, Player Name, 7654321234567890

json

The json helper allows you to serialize a value.

  • {{json server.name}} -> "The \"Best\" Example Server"
  • {{json 52}} -> 52
  • {{json undefined}} -> null

jsonObject

The jsonObject helper allows you to build valid JSON objects and can be nested or combined with the jsonArray helper.

  • {{jsonObject name=server.name players=server.players maxPlayers=server.maxPlayers}} -> {"name": "Example Server Name", "players": 50, "maxPlayers": 70}
{{jsonObject
server=(jsonObject
  name=server.name
  players=server.players
  maxPlayers=server.maxPlayers
)
player=(jsonObject
  name=player.name
  ip=player.ip
)}}
  • -> json { "server": { "name": "Example Server Name", "players": 50, "maxPlayers": 70 }, "player": { "name": "Player Name", "ip": "127.0.0.1" } }

jsonArray

The jsonArray helper allows you to build valid JSON arrays and can be nested or combined with the jsonObject helper.

  • {{jsonArray player.ip.country player.steam.country}} -> [null,"US"]

Examples

Player Message with Server

The following example will create a webhook that will send player messages using a Discord webhook. It should be used with the Player Message trigger type.

You can use the body below as a reference, or simply see the trigger on the BattleMetrics website.

{{jsonObject
  embeds=(jsonArray (jsonObject
    timestamp=timestamp.iso8601
    author=(jsonObject
      name=player.name
      url=(concatenate "https://www.battlemetrics.com/players/" player.id)
    )
    fields=(jsonArray
      (jsonObject
        name="Message"
        value=msg.body
      )
      (jsonObject
        name="Server"
        value=(concatenate "https://www.battlemetrics.com/rcon/servers/" server.id)
        inline=true
      )
    )
  ))
}}

Simple Player Message Webhook

The following example will create a webhook that will send player messages using a Discord webhook. It should be used with the Player Message trigger type.

You can use the body below as a reference, or simply see the trigger on the BattleMetrics website.

{{jsonObject
  embeds=(jsonArray (jsonObject
    title=player.name
    url=(concatenate "https://www.battlemetrics.com/players/" player.id)
    description=msg.body
  ))
}}

Admin Command Webhook

The following example will create a webhook that will send admin commands to Discord using a Discord webhook. It should be used with the Admin Command trigger type.

You can use the body below as a reference, or simply see the trigger on the BattleMetrics website.

{{jsonObject
  content=msg.body
  embeds=(jsonArray (jsonObject
    timestamp=timestamp.iso8601
    fields=(jsonArray
      (jsonObject
        name="Source"
        value=msg.commandSource
        inline=true
      )
      (jsonObject
        name="Command"
        value=msg.command
        inline=true
      )
      (jsonObject
        name="Server"
        value=(concatenate "https://www.battlemetrics.com/rcon/servers/" server.id)
        inline=true
      )
    )
  ))
}}

Still need help? Contact Us Contact Us