Freeflow

Guides

Roblox Webhooks: Complete Guide With Lua Examples

Roblox webhooks allow your Roblox experience or external application to communicate with other services automatically.

You can use webhooks to:

  • Send Roblox events to Discord
  • Log player activity
  • Record purchases
  • Send moderation alerts
  • Monitor game servers
  • Connect Roblox to an external website
  • Receive Roblox Open Cloud events
  • Build analytics systems
  • Trigger external automation

There are actually two different things developers often mean when they search for Roblox webhooks.

The first is sending data from a Roblox game to another service using HttpService.

The second is using Roblox's official webhook system, where Roblox sends an event to your server when something happens.

This guide covers both.

Freeflow Team•Sep 28, 2026•10 min read
01 /

What Is a Roblox Webhook?

A webhook is an HTTP request automatically sent when an event occurs.

Instead of repeatedly asking:

Has something happened yet?

a webhook allows the service to tell another system immediately.

A simplified flow looks like this:

Roblox Event
     ↓
Webhook / HTTP Request
     ↓
Your Server
     ↓
Discord / Database / Dashboard / API

For example, you could send a request whenever somebody purchases a developer product.

Player purchases product
        ↓
Roblox server detects purchase
        ↓
HttpService sends JSON
        ↓
Your webhook server receives it
        ↓
Discord notification appears
02 /

Roblox Webhooks vs HttpService

It is useful to understand the difference.

HttpService

HttpService runs from your Roblox experience.

Your game sends a request to another service.

Example:

Roblox game → your API

Roblox Open Cloud Webhooks

Roblox itself sends the request.

Example:

Roblox → your server

These are useful for supported Roblox platform events.

You can read our dedicated guide here:

Roblox Open Cloud Webhooks Guide

03 /

How to Enable HTTP Requests in Roblox Studio

Before sending webhook requests from your game, HTTP requests must be enabled.

In Roblox Studio:

  1. Open your experience.
  2. Open Game Settings.
  3. Select Security.
  4. Enable Allow HTTP Requests.
  5. Save your settings.

You can then use Roblox's HttpService.

04 /

Basic Roblox HTTP Request

Start by getting HttpService.

local HttpService = game:GetService("HttpService")

You can then send a POST request.

local HttpService = game:GetService("HttpService")

local url = "https://example.com/webhook"

local data = {
	message = "Hello from Roblox!"
}

local response = HttpService:RequestAsync({
	Url = url,
	Method = "POST",
	Headers = {
		["Content-Type"] = "application/json"
	},
	Body = HttpService:JSONEncode(data)
})

print(response.StatusCode)
print(response.Body)

This is the basic pattern used throughout most Roblox webhook systems.

05 /

Using PostAsync Instead

For very simple requests, you can also use PostAsync().

local HttpService = game:GetService("HttpService")

local url = "https://example.com/webhook"

local data = {
	username = "RobloxServer",
	message = "Server started"
}

local json = HttpService:JSONEncode(data)

HttpService:PostAsync(
	url,
	json,
	Enum.HttpContentType.ApplicationJson
)

RequestAsync() is generally more useful because it gives you access to:

  • Status code
  • Response body
  • Response headers
  • Success status
06 /

Safer Roblox Webhook Function

Production code should handle request failures.

local HttpService = game:GetService("HttpService")

local WEBHOOK_URL = "https://example.com/webhook"

local function sendWebhook(data)
	local success, response = pcall(function()

		return HttpService:RequestAsync({
			Url = WEBHOOK_URL,
			Method = "POST",

			Headers = {
				["Content-Type"] = "application/json"
			},

			Body = HttpService:JSONEncode(data)
		})

	end)

	if not success then
		warn("Webhook request failed:", response)
		return false
	end

	if not response.Success then
		warn(
			"Webhook returned HTTP",
			response.StatusCode,
			response.StatusMessage
		)

		return false
	end

	return true
end

Now sending an event is simple.

sendWebhook({
	type = "server_started",
	jobId = game.JobId,
	placeId = game.PlaceId
})
07 /

Roblox Player Join Webhook

You could log when somebody enters a server.

local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(player)

	sendWebhook({
		event = "player_join",

		player = {
			name = player.Name,
			displayName = player.DisplayName,
			userId = player.UserId
		},

		server = {
			jobId = game.JobId,
			placeId = game.PlaceId
		}
	})

end)

Example JSON sent by Roblox:

{
  "event": "player_join",
  "player": {
    "name": "ExamplePlayer",
    "displayName": "Example",
    "userId": 123456789
  },
  "server": {
    "jobId": "server-id",
    "placeId": 123456
  }
}
08 /

Roblox Player Leave Webhook

You can do the same when the player leaves.

local Players = game:GetService("Players")

Players.PlayerRemoving:Connect(function(player)

	sendWebhook({
		event = "player_leave",

		player = {
			name = player.Name,
			userId = player.UserId
		},

		server = {
			jobId = game.JobId,
			placeId = game.PlaceId
		},

		timestamp = os.time()
	})

end)
09 /

Roblox Server Start Webhook

This can be useful for monitoring live servers.

sendWebhook({
	event = "server_started",
	placeId = game.PlaceId,
	jobId = game.JobId,
	privateServerId = game.PrivateServerId,
	timestamp = os.time()
})
10 /

Roblox Server Shutdown Webhook

You can use BindToClose().

game:BindToClose(function()

	sendWebhook({
		event = "server_shutdown",
		placeId = game.PlaceId,
		jobId = game.JobId,
		timestamp = os.time()
	})

end)

Do not make shutdown logic depend entirely on an external webhook succeeding.

The server may be closing and you should treat the request as supplementary logging rather than critical game logic.

11 /

Roblox Purchase Webhook

Developer product purchases can be valuable events to send to an external system.

Your receipt handling still needs to follow Roblox's normal MarketplaceService receipt system.

Example structure:

local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

MarketplaceService.ProcessReceipt = function(receiptInfo)

	local player = Players:GetPlayerByUserId(
		receiptInfo.PlayerId
	)

	if not player then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end

	-- Grant your product here first.
	-- Your actual purchase processing should be idempotent.

	sendWebhook({
		event = "developer_product_purchase",

		player = {
			name = player.Name,
			userId = player.UserId
		},

		purchase = {
			productId = receiptInfo.ProductId,
			purchaseId = receiptInfo.PurchaseId
		},

		timestamp = os.time()
	})

	return Enum.ProductPurchaseDecision.PurchaseGranted
end

Do not use a webhook response as the system that decides whether the player receives the purchased product.

The purchase should be handled properly inside Roblox.

12 /

Roblox Game Pass Purchase Webhook

You can listen for completed game pass purchases.

local MarketplaceService = game:GetService("MarketplaceService")

MarketplaceService.PromptGamePassPurchaseFinished:Connect(
	function(player, gamePassId, purchased)

		if not purchased then
			return
		end

		sendWebhook({
			event = "gamepass_purchase",

			player = {
				name = player.Name,
				userId = player.UserId
			},

			gamePassId = gamePassId,
			timestamp = os.time()
		})

	end
)
13 /

Roblox Admin Command Webhook

A webhook can also log staff actions.

Imagine your admin system eventually calls:

local function logAdminCommand(player, command, arguments)

	sendWebhook({
		event = "admin_command",

		admin = {
			name = player.Name,
			userId = player.UserId
		},

		command = command,
		arguments = arguments,

		server = {
			jobId = game.JobId,
			placeId = game.PlaceId
		},

		timestamp = os.time()
	})

end

Then:

logAdminCommand(
	player,
	"kick",
	{
		target = "ExamplePlayer",
		reason = "Spam"
	}
)
14 /

Roblox Error Webhook

You can build an external error monitoring system.

For errors you control yourself:

local function reportError(systemName, errorMessage)

	sendWebhook({
		event = "game_error",
		system = systemName,
		message = tostring(errorMessage),
		jobId = game.JobId,
		placeId = game.PlaceId,
		timestamp = os.time()
	})

end

Example:

local success, result = pcall(function()

	-- Code that may fail

end)

if not success then
	reportError(
		"InventorySystem",
		result
	)
end
15 /

Create a Reusable Roblox Webhook Module

Instead of repeating webhook code throughout your experience, create a ModuleScript.

Example:

local HttpService = game:GetService("HttpService")

local Webhook = {}

local ENDPOINT = "https://example.com/api/roblox"

function Webhook.send(eventName, data)

	local payload = {
		event = eventName,
		data = data,
		server = {
			placeId = game.PlaceId,
			jobId = game.JobId
		},
		timestamp = os.time()
	}

	local success, response = pcall(function()

		return HttpService:RequestAsync({
			Url = ENDPOINT,
			Method = "POST",

			Headers = {
				["Content-Type"] = "application/json"
			},

			Body = HttpService:JSONEncode(payload)
		})

	end)

	if not success then
		warn(
			"[Webhook] Request failed:",
			response
		)

		return false
	end

	if not response.Success then
		warn(
			"[Webhook] HTTP error:",
			response.StatusCode
		)

		return false
	end

	return true
end

return Webhook

Then another server script can simply do:

local Webhook = require(
	game.ServerScriptService.Webhook
)

Webhook.send("player_reward", {
	userId = 123456789,
	reward = "Daily Chest"
})
16 /

Add Authentication to Your Roblox Webhook

Do not leave your receiving endpoint completely open.

At minimum, send a shared token.

local response = HttpService:RequestAsync({
	Url = WEBHOOK_URL,
	Method = "POST",

	Headers = {
		["Content-Type"] = "application/json",
		["Authorization"] = "Bearer YOUR_TOKEN"
	},

	Body = HttpService:JSONEncode(data)
})

Your web server can reject requests without the correct token.

However, avoid placing highly valuable secrets directly inside Roblox scripts when possible.

For sensitive systems, use an architecture designed around server-side secrets and Roblox's supported secret-management features.

17 /

Add a Request ID

Giving every event an ID helps prevent accidental duplicates.

local HttpService = game:GetService("HttpService")

local requestId = HttpService:GenerateGUID(false)

sendWebhook({
	requestId = requestId,
	event = "purchase",
	userId = 123456789
})

Example:

28ef2eac-f409-43b5-8e49-58cfbd8b201c

Your external server can store processed IDs and ignore duplicates.

18 /

Add Timestamps

Use Unix timestamps:

local timestamp = os.time()

Payload:

sendWebhook({
	event = "player_join",
	timestamp = os.time()
})

This is useful for:

  • Logs
  • Sorting
  • Analytics
  • Debugging
  • Duplicate detection
19 /

Batch Roblox Webhook Events

Sending one HTTP request for every tiny game event is rarely a good idea.

Instead, batch events.

local queue = {}

local function addEvent(event)

	table.insert(queue, event)

end

Add:

addEvent({
	type = "coin_collected",
	userId = player.UserId,
	amount = 10,
	time = os.time()
})

Then periodically send them together.

task.spawn(function()

	while true do

		task.wait(10)

		if #queue > 0 then

			local eventsToSend = queue
			queue = {}

			sendWebhook({
				event = "batch",
				events = eventsToSend
			})

		end

	end

end)

This can dramatically reduce unnecessary HTTP traffic.

20 /

Roblox Discord Webhooks

One of the most common uses of Roblox webhooks is sending notifications to Discord.

A typical setup looks like:

Roblox
   ↓
Your webhook relay
   ↓
Discord webhook

You should avoid exposing your Discord webhook URL inside code that may become accessible to people who shouldn't have it.

Your relay can also provide:

  • Authentication
  • Rate limiting
  • Filtering
  • Logging
  • Webhook URL protection
  • Message formatting

We've written a complete implementation here:

How to Use Roblox Discord Webhooks

21 /

Roblox Open Cloud Webhooks

Webhooks can also work in the opposite direction.

Roblox can notify your application when supported platform events occur.

The flow becomes:

Roblox
   ↓
Webhook Notification
   ↓
Your Public Endpoint
   ↓
Your Application

Roblox webhook notifications can be configured through Creator Hub.

You should use webhook secrets and validate incoming Roblox signatures when building a custom endpoint.

Read the full setup here:

Roblox Open Cloud Webhooks Guide

22 /

What Can Roblox Webhooks Be Used For?

Some useful ideas include:

Moderation

Ban issued
↓
External moderation log

Purchases

Developer product purchase
↓
Sales dashboard

Analytics

Player completes level
↓
Analytics API

Discord

Important game event
↓
Discord staff channel

Server Monitoring

Server starts or shuts down
↓
Monitoring dashboard

Bug Reports

Player submits report
↓
Support system

External Websites

Game event
↓
Freeflow-style dashboard
↓
Live statistics
23 /

What Should You Not Send Through Roblox Webhooks?

Avoid sending unnecessary sensitive information.

For example, do not build systems that indiscriminately forward:

  • Private player information
  • Authentication credentials
  • API keys
  • Private moderation information
  • Personal information you don't need

Send only the information your integration actually requires.

24 /

Roblox Webhook Security Tips

A production webhook system should follow several basic practices.

Keep External Secrets Off the Client

Never put webhook credentials inside a LocalScript.

Client code should not be trusted.

Validate Requests

Your receiving server should authenticate requests.

Rate Limit Requests

Do not allow players to generate unlimited outbound requests.

Sanitize User Input

Never assume user-submitted text is safe.

Use HTTPS

Your endpoint should use HTTPS.

Handle Failures

External APIs can fail.

Your Roblox game should continue functioning even when a logging webhook is temporarily unavailable.

25 /

Roblox Webhook Example Architecture

A stronger production architecture looks like this:

Roblox ServerScript
        ↓
HttpService
        ↓
Your API
        ↓
Authentication
        ↓
Validation
        ↓
Rate Limit
        ↓
Queue
        ↓
Discord / Database / Dashboard

This gives you far more control than sending important data directly to third-party services.

Frequently Asked Questions

What is a Roblox webhook?+

A Roblox webhook is an HTTP-based integration that allows Roblox and another service to automatically exchange information when certain events occur.

Can Roblox send webhooks?+

Yes. Roblox experiences can use HttpService to send HTTP requests to external services. Roblox also provides official webhook notifications for supported Open Cloud events.

Can Roblox webhooks send messages to Discord?+

Yes, but a reliable production setup normally uses an external relay between the Roblox game and Discord rather than depending on a direct live-server request to Discord.

What is HttpService in Roblox?+

HttpService is a Roblox service that allows server scripts to communicate with supported external web services using HTTP requests.

Do Roblox HTTP requests have to be enabled?+

Yes. HTTP requests need to be enabled in your Roblox experience's security settings before normal HttpService outbound requests can be used.

Should I put my webhook URL in a LocalScript?+

No. Sensitive integration details should not be exposed in client-side code.

Can Roblox receive webhooks?+

Your individual running Roblox game server is not normally used as a public HTTP webhook server. Instead, Roblox webhook notifications are sent to a publicly accessible external endpoint that you control.

26 /

More Roblox Development Guides