# Inline UI

{% stepper %}
{% step %}
**Create Your UI Code**

Build your key validation UI using the Junkie UI-Library:

```
-- This loads the Junkie-Library
local Junkie = loadstring(game:HttpGet("https://jnkie.com/sdk/library.lua"))()
Junkie.service = "YOUR_SERVICE"  -- Your service name from dashboard
Junkie.identifier = "12345"  -- Your user ID from dashboard
Junkie.provider = "Mixed"  -- Your provider name

-- UI CODE -> This is just an example dont fully copy it!
local result = Junkie.check_key(keyToCheck)
if result and result.valid then
    getgenv().SCRIPT_KEY = keyToCheck
else
    print("Invalid Key")
end


while not getgenv().SCRIPT_KEY do
    task.wait(0.1)
end

-- -> Junkie Loadstring here
```

{% endstep %}

{% step %}
**Obfuscate Your Code**

Before uploading, you SHOULD obfuscate your UI code:

{% hint style="info" %}
**Recommended Free Obfuscator**

[Prometheus Obfuscator](https://wearedevs.net/obfuscator) - Free, powerful, and easy to use

1. Copy your unobfuscated UI code
2. Paste into Prometheus Obfuscator
3. Click "Obfuscate"
4. Copy the obfuscated result
   {% endhint %}
   {% endstep %}

{% step %}
**Upload to Dashboard**

Upload your obfuscated UI code to the dashboard:

1. Go to Dashboard → Lua Scripts
2. Create new script or edit existing
3. Find the **UI-Source** field (above Original Code)
4. Paste your obfuscated UI code
5. In **Original Code** field, put your main script
6. Click Save
   {% endstep %}

{% step %}
**Response Cases for check\_key()**

The function returns different responses based on validation:

{% hint style="success" %}
**Success - Keyless Mode**

```
{ valid = true, message = "KEYLESS" }
```

{% endhint %}

{% hint style="success" %}
**Success - Valid Key**

```
{ valid = true, message = "KEY_VALID" }
```

{% endhint %}

{% hint style="danger" %}
**Common Errors**

**HTTP Request Failed:**

```
{ valid = false, error = "ERROR" }
```

**HTTP Error (4xx/5xx):**

```
{ valid = false, error = "http 429" -- or other status code }
```

**Backend Validation Errors:**

```
-- Invalid/expired/banned keys return:
 { valid = false, error = <backend error message> }
 -- All possible backend messages: 
-- "KEY_INVALID" - Key not found 
-- "KEY_EXPIRED" - Key past expiration 
-- "HWID_BANNED" - Hardware banned 
-- "KEY_INVALIDATED" - Key manually disabled 
-- "ALREADY_USED" - One-time key used 
-- "HWID_MISMATCH" - HWID limit reached 
-- "SERVICE_NOT_FOUND" - Service doesn't exist 
-- "SERVICE_MISMATCH" - Key for different service 
-- "PREMIUM_REQUIRED" - Premium key needed
```

{% endhint %}
{% endstep %}

{% step %}
**Response Cases for get\_key\_link()**

Function returns two values: link and error message.

{% hint style="success" %}
**Success**

```
local link, err = Junkie.get_key_link() 
-- Returns: "https://jnkie.com/flow/abc-123...", nil
```

{% endhint %}

{% hint style="warning" %}
**Rate Limited**

```
local link, err = Junkie.get_key_link()
-- Returns: nil, "RATE_LIMITTED"
-- Wait 5 minutes between requests
```

{% endhint %}

{% hint style="danger" %}
**Errors**

**Request Failed:**

```
-- Returns: nil, "ERROR"
```

**Other HTTP Errors:**

```
-- Returns: nil, <error message from server>
```

{% endhint %}
{% endstep %}

{% step %}
**Complete Example with Error Handling**

```
local Junkie = loadstring(game:HttpGet("https://jnkie.com/sdk/library.lua"))()
Junkie.service = "Premium Hub"
Junkie.identifier = "12345"
Junkie.provider = "Mixed"

local result = (function()
    getgenv().SCRIPT_KEY = nil
    getgenv().UI_CLOSED = false
    
    local maxAttempts = 5
    local attempts = 0
    
    while not getgenv().SCRIPT_KEY and not getgenv().UI_CLOSED do
        task.wait(0.1)
        
        -- Get user input (replace with your UI logic)
        local userInput = yourUIGetInput()
        
        if userInput == "GET_LINK" then
            local link = Junkie.get_key_link()
            if link then
                yourUIShowLink(link)  -- Display link to user
            else
                yourUIShowError("Rate limited! Wait 5 minutes")
            end
        elseif userInput and #userInput > 0 then
            attempts = attempts + 1
            
            if attempts > maxAttempts then
                yourUIShowError("Too many failed attempts!")
                getgenv().UI_CLOSED = true
                break
            end
            
            local validation = Junkie.check_key(userInput)
            
            if validation.success then
                getgenv().SCRIPT_KEY = userInput
                yourUIShowSuccess("Key validated!")
                break
            else
                local errorMsg = validation.error or "Unknown error"
                yourUIShowError(errorMsg)
                
                -- Handle all possible backend error messages
                if errorMsg == "KEY_INVALID" then
                    yourUIShowInfo("Key not found in system")
                elseif errorMsg == "KEY_EXPIRED" then
                    yourUIShowInfo("Key expired - get a new one")
                elseif errorMsg == "HWID_BANNED" then
                    game.Players.LocalPlayer:Kick("Hardware banned")
                    return nil
                elseif errorMsg == "KEY_INVALIDATED" then
                    yourUIShowInfo("Key was manually disabled")
                elseif errorMsg == "ALREADY_USED" then
                    yourUIShowInfo("One-time key already used")
                elseif errorMsg == "HWID_MISMATCH" then
                    yourUIShowInfo("HWID limit reached")
                elseif errorMsg == "SERVICE_NOT_FOUND" then
                    yourUIShowInfo("Service doesn't exist")
                elseif errorMsg == "SERVICE_MISMATCH" then
                    yourUIShowInfo("Key is for a different service")
                elseif errorMsg == "PREMIUM_REQUIRED" then
                    yourUIShowInfo("Premium key required for this service")
                elseif errorMsg == "ERROR" then
                    yourUIShowError("Network error - try again")
                elseif errorMsg:match("^http %d+") then
                    yourUIShowError("Server error: " .. errorMsg)
                end
            end
        end
    end
    
    return getgenv().SCRIPT_KEY
end)()

if not result then
    warn("UI closed without valid key")
    return
end
```

{% endstep %}
{% endstepper %}

{% columns %}
{% column %}
{% hint style="success" %}
**Advantages**

* Full UI customization
* All code hosted on Junkie CDN
* Double obfuscation (UI + Main)
* No external dependencies
  {% endhint %}
  {% endcolumn %}

{% column %}
{% hint style="warning" %}
**Considerations**

* Must obfuscate UI yourself
* UI updates require re-upload
* Need while-loop or external load
  {% endhint %}
  {% endcolumn %}
  {% endcolumns %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.jnkie.com/roblox-sdk/inline-ui.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
