Sinful Management
SINFUL Developer documentation
Developer API v1

Developer API

Use the Sinful Management API to work with projects, licenses, and authentication logs from your own trusted backend services.

Server-side use only

API credentials should never be embedded in Roblox, distributed Lua, or browser code. Keep them inside a trusted server environment.

Authentication

Create a scoped credential from Dashboard → API credentials. Send that credential as a Bearer token with each request.

HTTP header
Authorization: Bearer sm_api_YOUR_SECRET

Projects

Retrieve projects available to the authenticated API credential.

GET /developer/v1/projects

Required scope: projects:read

List licenses

Retrieve license records for a project.

GET /developer/v1/licenses?projectId=PROJECT_ID

Required scope: keys:read

The response exposes license fingerprints and status, not raw license keys.

Generate licenses

Generate license keys within the limits of the workspace's active Sinful Management plan.

POST /developer/v1/licenses

Required scope: keys:write

A single request can generate up to 1,000 keys, subject to plan limits.

Revoke a license

Revoke an existing license and terminate the runtime sessions attached to it.

POST /developer/v1/licenses/LICENSE_ID/revoke

Required scope: keys:write

Authentication logs

Read project-scoped authentication and management activity.

GET /developer/v1/logs?projectId=PROJECT_ID

Required scope: logs:read

Runtime configuration

Server Capabilities

Server Capabilities let a protected script request developer-controlled runtime values from Sinful Management. Capabilities are scoped to the script that owns them and are available only through an authenticated Sinful runtime.

Three capability types are available: Feature Flags, Protected Values, and Server Actions.

Enable the master switch first

Open Dashboard → Scripts → Edit and enable Server Capabilities. Capabilities configured for a script are rejected at runtime while this master switch is disabled.

Creating a capability

Open Dashboard → Scripts, choose Capabilities for the script, then select New capability.

Capability names are lowercase identifiers such as premium_enabled, maintenance_mode, or api_endpoint.

Basic Lua usage
local value = SinfulCapability("premium_enabled")

Feature Flags

A Feature Flag is a server-controlled boolean. It returns either true or false to the authorized script.

Feature Flags are useful for enabling or disabling optional behavior without rebuilding and redistributing the developer's Lua source.

Feature Flag
local premium = SinfulCapability("premium_enabled")

if premium then
    print("Premium features enabled")
else
    print("Premium features disabled")
end
Runtime controlled

Changing the Feature Flag in the dashboard changes the value returned by future capability requests. The developer does not need to place the flag value directly in their Lua source.

Example uses

Feature Flags can control premium features, maintenance behavior, staged rollouts, experimental functionality, or other boolean decisions that the developer wants to control from the dashboard.

Protected Values

A Protected Value stores developer-provided configuration in Sinful Management instead of placing that value directly in the uploaded Lua source.

Protected Values are encrypted when stored by Sinful Management. The dashboard capability list does not return the stored value after it has been saved.

Protected Value
local apiBase = SinfulCapability("api_endpoint")

print(apiBase)

Updating a Protected Value

When editing an existing Protected Value, its current value is intentionally not displayed. Enter a replacement only when you want to change it. Leaving the replacement field blank keeps the existing stored value.

Protected does not mean permanently secret

A value intentionally returned to an authorized Roblox/Lua client can potentially be observed by that client. Protected Values are appropriate for server-controlled configuration, identifiers, endpoints, entitlement data, and similar runtime values. Do not use them for credentials that must never reach the client.

Master API credentials, signing private keys, database passwords, provider secrets, and similar high-value secrets should remain exclusively on a trusted server.

Server-side operations

Server Actions

Server Actions let protected Lua request a predefined operation that Sinful Management performs on the server. Unlike a Feature Flag or Protected Value, a Server Action is not simply a stored value lookup.

Developers choose from operations implemented and allowlisted by Sinful Management. Developer-provided Lua, JavaScript, shell commands, arbitrary HTTP requests, and other arbitrary server-side code are not executed.

Server-side operation, client-visible result

The operation and authoritative state change occur on the Sinful Management server. Any result intentionally returned to Lua can still be observed or modified by a hostile authorized client, so security-sensitive authority should remain in the server-side operation itself.

Using a Server Action

SinfulAction(name, input) is injected into protected script source by Sinful Management. Use the exact Server Action name configured for the script.

Lua
local result = SinfulAction("increment_launches")

print(result.value)

Counter Increment

Counter Increment atomically increments a named integer counter maintained by Sinful Management and returns the new value.

Configure the action with a counter name such as launches. The client does not choose the counter name or increment amount at runtime.

Counter Increment
local result = SinfulAction("increment_launches")
print("Launch count:", result.value)

Counter Read

Counter Read returns the current value of a named counter without changing it.

A Counter Read action and Counter Increment action configured with the same counter name share the same authoritative state when they belong to the same project and script.

Counter Read
local result = SinfulAction("read_launches")
print("Launch count:", result.value)

Shared counter example

For example, configure two Server Actions: increment_launches using Counter Increment and read_launches using Counter Read. Set the counter name of both actions to launches.

Shared state
local before = SinfulAction("read_launches")
print("Before:", before.value)

local incremented = SinfulAction("increment_launches")
print("Incremented:", incremented.value)

local after = SinfulAction("read_launches")
print("After:", after.value)

Optional input

SinfulAction() supports an optional input table for Server Action types that accept validated client input:

Function signature
local result = SinfulAction("action_name", { })

The current Counter Read and Counter Increment handlers accept no client-controlled parameters. Passing fields to those actions is rejected.

Failure handling

Use pcall when an action is optional or when your script should handle a runtime failure gracefully.

Lua
local ok, result = pcall(function()
    return SinfulAction("read_launches")
end)

if not ok then
    warn("[Sinful] Server Action failed:", result)
    return
end

print(result.value)
Do not call runtime endpoints directly

Developers should use SinfulAction(). Sinful Management handles runtime authentication, the short-lived one-time action grant, context binding, grant consumption, and execution of the allowlisted server operation.

Authorization model

Each Server Action request requires the protected authenticated runtime. Sinful Management issues a short-lived, one-time action grant bound to the current runtime context and the specific Server Action. The grant is consumed before the operation runs.

Server Actions are isolated from normal capability retrieval. A Server Action must be called with SinfulAction(); it cannot be retrieved through SinfulCapability().

Using capabilities in Lua

SinfulCapability(name) is injected into protected script source by Sinful Management before the source is processed for distribution.

Call it from the developer source using the exact capability name configured for that script.

Feature Flag
local enabled = SinfulCapability("premium_enabled")
Protected Value
local endpoint = SinfulCapability("api_endpoint")
Server Action
local result = SinfulAction("increment_launches")

Recommended optional-capability pattern

If a capability controls optional functionality, developers can use pcall and provide a safe fallback.

Lua
local function capability(name, fallback)
    local ok, value = pcall(function()
        return SinfulCapability(name)
    end)

    if not ok then
        warn("[Sinful] Capability failed:", value)
        return fallback
    end

    return value
end

local premium = capability("premium_enabled", false)

if premium then
    -- premium functionality
end
Do not copy the runtime endpoints into your source

Developers should use SinfulCapability(). Sinful Management handles the authenticated runtime requests, one-time capability grant, and capability retrieval.

Capability error handling

A capability request can fail when the capability does not exist, is disabled, the script's Server Capabilities master switch is disabled, or the runtime authorization is no longer valid.

Developers should decide whether a capability is required or optional. Required configuration can stop execution on failure; optional configuration should normally use a safe fallback.

Required capability
local ok, value = pcall(function()
    return SinfulCapability("required_config")
end)

if not ok then
    error("Required capability unavailable: " .. tostring(value))
end

Capability security model

Server Capabilities are part of the protected Sinful runtime. A normal capability lookup is not a public unauthenticated value endpoint.

The runtime first requests a short-lived capability grant. The grant is bound to the authenticated runtime context and is consumed when the capability is retrieved.

One-time runtime authorization

Capability retrieval uses short-lived, one-time authorization tied to the active protected runtime rather than exposing capability values through the public Developer API.

Capability isolation

Capabilities belong to a specific protected script. A script can request its own enabled capabilities through its authorized runtime context.

What this protects

Server Capabilities let developers move selected configuration and feature decisions out of static Lua source and control them from Sinful Management.

Server Actions and client trust

Server Actions can keep authoritative operations and state changes on the server instead of implementing those operations entirely in distributed Lua. Patching a local boolean does not perform the corresponding server-side operation.

However, a result returned by SinfulAction() becomes visible to the authorized client. Client code can potentially ignore, replace, or misrepresent that returned value. Design security-sensitive actions so the server-side mutation or decision, rather than trust in the returned Lua value, is authoritative.

What this does not protect

No client-side system can guarantee confidentiality after a value is intentionally delivered to a hostile authorized client. Logic or secrets that must never be exposed should remain entirely server-side.

Generate keys

Example request for generating ten 30-day license keys.

cURL
curl -X POST https://www.sinfulmanagement.com/developer/v1/licenses \
  -H "Authorization: Bearer sm_api_YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"PROJECT_ID","scriptId":"SCRIPT_ID","quantity":10,"days":30}'

Credential security

Raw generated license keys are returned once. API credentials should also be treated as secrets.

Credential exposed?

Revoke the affected API credential immediately and issue a replacement before continuing to use the integration.