Charge for Your Scripting System in 3 Milestones
You delivered the system, the client said he'd test it tonight and never came back — and there is no ticket that gets your Robux back. Split the price into three gamepasses in your own place and hand over the source file only after the last payment clears.
AI-assisted draft, reviewed, tested and edited by a human before publishing. See our Editorial Policy. · Reviewed by Gustavo Cantino, 9/20/26 Editorial Policy

You charge for a scripting system without getting stiffed by making the client buy a gamepass in your own place, split into three milestones, and handing over the final file only after the last payment clears. There is no contract Roblox enforces on your behalf: if the client already has the .rbxm in hand and hasn't paid, there is no support ticket and no DMCA that resolves it in any useful timeframe. What does exist is delivery sequence — whoever controls the order of the steps controls the risk.
The scam doesn't happen at delivery, it happens in the payment method
The script is always the same. You close a shop system with inventory and saving for 70,000 Robux, work two or three weeks, and the client asks for it "just to see it running in my game". You send the model, he answers "nice, I'll test it tonight" and never shows up again. Or worse: he shows up just long enough to ask for three more tweaks for free.
Put a price on that. 70,000 net Robux are worth US$ 245 at DevEx (the rate is 100,000 Robux = US$ 350). With the dollar at R$ 5.40 — check the day's quote and your bank's fee — that's about R$ 1,323 that vanished along with the file. Divide it by three weeks of work and you just worked for less than an intern's floor.
And there's the part almost everybody forgets when writing the quote: gamepasses and dev products leave 30% with Roblox. If you agreed on 70,000 Robux and set the gamepass price to 70,000, then 49,000 land in your account. You already lost 21,000 Robux (US$ 73.50) before any scam even happened.
The other variation of the loss is the most elegant of them all, and it's the one that catches good devs: the client invites you into his group and promises to pay through group payout. Group payout only releases funds to people who have been in the group for 14 days. On day 12, with the system already running in his game, you get removed from the group. The money was never transferred, there is no purchase record, there is nothing to complain about. You volunteered.
Billing in three milestones, with the money landing in your place
The flow below doesn't depend on trust, and it's fast to set up — you can have everything ready in about 20 minutes per client.
1. Written scope before the price. A list of deliverables, the number of revisions included, and the GameId of the authorized universe. The GameId is what the license ties itself to later, so ask the client to run print(game.GameId) in his place and send you the number (it is not the PlaceId from the URL — one universe holds several places). Without a written scope, "shop system" becomes "shop system, plus trading, plus a leaderboard" by week three.
2. Gross price = net price ÷ 0.7. If you want 70,000 Robux in your account, the gamepasses have to add up to 100,000 Robux. Do that math in front of the client and show it in the proposal: gross, net, and what you actually receive. That moves the conversation from "this is expensive" to "Roblox takes 30%".
3. Three gamepasses, in your place, named after the milestones. Create three gamepasses in a place that is yours (it can be private — the client buys straight from the gamepass page on the website) with explicit names: "Milestone 1 — Shop System", "Milestone 2", "Milestone 3". A split that works: 40% on scope signing, 40% on delivery of the test build, 20% on releasing the license and the source file. The milestone table is in the artifact, with gross, net and the dollar equivalent of each installment.
Why a gamepass and not Pix or a payout: a gamepass purchase has no refund button. The client doesn't open a dispute, doesn't cancel, doesn't reverse it. The money lands in your account immediately and shows up in your sales summary with a date and a buyer. It's the only mechanism inside the platform where money only moves in one direction.
4. Milestone 2 delivers a locked build, not the file. After the second payment you deliver the system working inside the client's game — but with the license module turned on, with a deadline. The system runs at 100% during the test and shuts itself off on the date you set. The client validates it in his own game, with real players, and you gave up nothing. Call the license on the first line of every script in your system:
local License = require(script.Parent.SpawnPointLicense)
if not License.assert() then
return -- system off: no red errors, just a warn in the output
end5. Milestone 3 releases the license and the source. Once the third gamepass is paid, you swap TRIAL_EXPIRES_AT for 0 (license with no deadline), confirm the final GameId and send the .rbxm plus the documentation. From here on the system is his, and that is exactly why this step is the last one.
6. Only then think about cashing out. DevEx requires a minimum of 30,000 Robux per request, an account with active Premium, age 13 or older, and identity verification. Notice that Milestone 1 in the example (28,000 net Robux) does not reach the minimum on its own — you accumulate until you clear the floor. And the money arrives as foreign income: an individual declares it in the carnê-leão, at a rate that reaches 27.5%. Confirm with an accountant before treating the full amount as profit.
The three files you send along with the quote
There are three artifacts and each one solves a piece of the problem.
The milestone table you paste straight into the conversation with the client. It shows gross, net, dollars, and what happens at each stage. Change only the total; the 70% and DevEx columns follow the same math.
The scope in JSON goes attached to the proposal. It looks like excessive formality for a Roblox freelance gig, but it's the document you pull up when the client asks for the fourth free revision: it's written down that there are two.
The license module is a ModuleScript you drop inside the delivered system. It compares game.GameId against the list of authorized universes, checks the trial deadline, and if something doesn't match it returns false and writes a warn in the output with your contact info. It does not delete anything, doesn't touch DataStores and doesn't break the client's game — sabotage gets you reported and burns your name in the freelance market, which is small and talks to itself. The system simply doesn't turn on.
One thing you need to know before trusting it too much: the check is friction, not encryption. Whoever has the file can open the module and delete the verification line. That's why the module protects the Milestone 2 build (which runs in the client's place, with the script on the server side, without him having the file) and does not replace the rule of delivering the source only at the end. And never run the check on the client:
if game.PlaceId ~= 123456789 then
script:Destroy() -- any exploiter turns this off in 10 seconds
endEverything that runs in StarterPlayerScripts or ReplicatedStorage gets read and edited by anybody who wants to. The license lives in ServerScriptService, together with the rest of your system.
The most expensive mistake: accepting "join my group and I'll do the payout"
This is the one that costs the entire value of the project, not one installment. Group payout has a 14-day membership waiting period, and it's the client who decides whether you're still in the group on day 14. I've seen this combination of rules described as the "group scam" on dev forums precisely because it is legitimate from the platform's point of view: no rule was broken, no transaction failed, there simply never was a transaction.
If you're already in the middle of a project set up that way, the fix is immediate and it's one sentence: "I can get paid through a gamepass, that way the purchase is on record for both of us". If the client accepts, the problem is over. If he insists on the payout, stop writing code until the first milestone lands. A client who argues against having the payment on record is telling you what he intends to do.
Two variations that fall in the same bucket: creating the gamepass in the client's place (then the money lands in his account, not yours — the gamepass belongs to whoever owns the game) and accepting a percentage of future revenue instead of a fixed amount. A percentage without access to the analytics dashboard and without control of the gamepass is a promise, not a payment. If you want a cut, charge the full fixed price plus the percentage, and assume the percentage may come out to zero.
What to measure starting from your first contract
Open a spreadsheet and log three numbers per quote you send.
The first is the Milestone 1 conversion rate: how many quotes sent turned into a first gamepass purchase. That number tells you whether your price and your proposal make sense for the market you're serving.
The second is the time between milestones, in days. If Milestone 2 takes 20 days to get paid because the client is "still testing", your trial window in the license module is too long — 14 days handles most cases.
The third is the real net per hour worked. Add up the project's hours, divide the net Robux, and convert at the DevEx rate. It's the only number that answers whether it's worth continuing to take scripting freelance work or whether it's time to put those same weeks into a game of your own.
Ready-to-use artifact
{
"project": "Store System v1",
"dev": "@your_roblox_username",
"client": "@client_username",
"authorized_universe": {
"game_id": 7654321098,
"how_to_get": "client runs print(game.GameId) in the production place"
},
"deliverables": [
"Inventory ModuleScript with saving to DataStore",
"Store GUI with 3 categories and search",
"RemoteEvents with server-side validation",
"1-page documentation in Portuguese"
],
"out_of_scope": [
"trading between players",
"global leaderboard",
"art and item icons"
],
"payment": {
"currency": "Robux",
"method": "gamepass in the dev's place",
"group_payout_accepted": false,
"gross_total": 100000,
"net_total_dev": 70000,
"milestones": [
{ "number": 1, "trigger": "scope approved", "gross": 40000, "gamepass_id": 0 },
{ "number": 2, "trigger": "test build with 14-day license", "gross": 40000, "gamepass_id": 0 },
{ "number": 3, "trigger": "license with no expiration + .rbxm file", "gross": 20000, "gamepass_id": 0 }
]
},
"revisions_included_per_milestone": 2,
"extra_revision_gross": 5000,
"test_period_days": 14,
"source_delivered_at": "milestone 3"
}# Marcos de pagamento — Sistema de Loja v1
Total combinado (liquido para o dev): **70.000 Robux**
Preco bruto necessario: 70.000 / 0,7 = **100.000 Robux** (a Roblox retem 30% de cada gamepass)
Conversao usada: 100.000 Robux = US$ 350 no DevEx | dolar de referencia R$ 5,40
| Marco | Gatilho | Gamepass (bruto) | Voce recebe (70%) | DevEx (US$) | ~R$ |
|---|---|---|---|---|---|
| 1 | Escopo assinado, antes da primeira linha de codigo | 40.000 | 28.000 | 98,00 | 529,20 |
| 2 | Build de teste rodando no jogo do cliente, com licenca por 14 dias | 40.000 | 28.000 | 98,00 | 529,20 |
| 3 | Licenca sem prazo + arquivo .rbxm + documentacao | 20.000 | 14.000 | 49,00 | 264,60 |
| **Total** | — | **100.000** | **70.000** | **245,00** | **1.323,00** |
Observacoes que ficam na proposta:
- Marco 1 sozinho (28.000) fica abaixo do minimo de 30.000 Robux por solicitacao de DevEx.
- Revisoes incluidas: 2 por marco. A terceira em diante e orcada a 5.000 Robux brutos cada.
- Os 3 gamepasses ficam em place de propriedade do dev. Group payout nao e aceito como forma de pagamento.--!strict
-- SpawnPointLicense
-- Where it lives: ServerScriptService, inside the folder of the system you deliver.
-- What it's for: enable the system only in the contracted universe and only
-- within the deadline of the test build (Milestone 2). In Milestone 3, swap
-- TRIAL_EXPIRES_AT for 0 and the license becomes valid with no deadline.
-- It does NOT delete anything and does NOT touch DataStore: if the license is not valid, the
-- system simply does not start and writes a warning to the Output.
local RunService = game:GetService("RunService")
export type LicenseResult = {
ok: boolean,
reason: string,
}
-- GameId (not PlaceId) of the authorized universes.
-- Ask the client to run print(game.GameId) in their place.
local AUTHORIZED_GAME_IDS: { [number]: boolean } = {
[7654321098] = true,
}
-- UTC timestamp of the end of the test. Use 0 for a permanent license (no deadline).
-- Example: 1767225600 = 01/01/2026 00:00 UTC
local TRIAL_EXPIRES_AT: number = 1767225600
local SYSTEM_NAME: string = "Shop System v1"
local CONTACT: string = "Trial license ended. Talk to the dev to unlock the final version."
local License = {}
-- Raw check: returns the result and the reason, without writing anything.
function License.check(): LicenseResult
-- Local unpublished file (GameId 0) runs freely, so you can develop.
if RunService:IsStudio() and game.GameId == 0 then
return { ok = true, reason = "local unpublished file" }
end
if not AUTHORIZED_GAME_IDS[game.GameId] then
return {
ok = false,
reason = string.format("GameId %d not authorized", game.GameId),
}
end
if TRIAL_EXPIRES_AT > 0 and os.time() > TRIAL_EXPIRES_AT then
return { ok = false, reason = "trial period expired" }
end
return { ok = true, reason = "valid license" }
end
-- Days remaining in the trial. Returns math.huge when the license has no deadline.
function License.daysLeft(): number
if TRIAL_EXPIRES_AT <= 0 then
return math.huge
end
return math.max(0, math.floor((TRIAL_EXPIRES_AT - os.time()) / 86400))
end
-- Call it on the first line of every Script in your system:
-- if not License.assert() then return end
function License.assert(): boolean
local result = License.check()
if not result.ok then
warn(string.format("[%s] disabled: %s. %s", SYSTEM_NAME, result.reason, CONTACT))
return false
end
if TRIAL_EXPIRES_AT > 0 then
print(string.format(
"[%s] test build active — %d day(s) remaining",
SYSTEM_NAME,
License.daysLeft()
))
end
return true
end
return LicenseIn this article
- The scam doesn't happen at delivery, it happens in the payment method
- Billing in three milestones, with the money landing in your place
- The three files you send along with the quote
- The most expensive mistake: accepting "join my group and I'll do the payout"
- What to measure starting from your first contract

