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 readWhat 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
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:
How to Enable HTTP Requests in Roblox Studio
Before sending webhook requests from your game, HTTP requests must be enabled.
In Roblox Studio:
- Open your experience.
- Open Game Settings.
- Select Security.
- Enable Allow HTTP Requests.
- Save your settings.
You can then use Roblox's HttpService.
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.
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
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
})
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
}
}
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)
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()
})
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.
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.
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
)
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"
}
)
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
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"
})
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.
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.
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
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.
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:
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:
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
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.
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.
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.
More Roblox Development Guides
Continue with:
Roblox Discord Webhooks: Complete Setup Guide
Roblox Open Cloud Webhooks Guide
You can also browse Roblox scripts and development assets on Freeflow.