# Roblox Studio

Track creator attributions and validate creator codes from a Roblox experience using the Nexus API.

The Nexus Roblox Studio integration tracks creator attributions and manages creator codes within your Roblox experience. It lets players link their purchases to specific creators through creator codes, enabling accurate attribution tracking and commission distribution.

Before the installation steps, you need Nexus API keys: a public key for code validation and a private (secret) key for attribution.

<LinkCard title="Download the example project (.rbxl)" description="An example Roblox Studio project for the Nexus integration." href="https://drive.google.com/file/d/1Jb2Hu625bSCOBIbKg7EcYTwySd_Y5y78/view?usp=sharing" />

## Features

* **Creator code management**: Players can enter and validate creator codes
* **Purchase attribution**: Automatic tracking of purchases with creator attribution
* **Member data storage**: Persistent storage of member information using DataStore
* **API integration**: Communicates with Nexus API endpoints
* **Product management**: Centralized product configuration and handling

## Architecture

The integration consists of several interconnected modules:

* **S\_NexusServices**: Handles creator code validation and management
* **S\_PurchaseServices**: Processes purchases and creates attribution transactions
* **MS\_NexusApiManager**: Manages all API communications with Nexus
* **MS\_PlayerDataStore**: Handles persistent data storage for players (option: example usage)
* **MS\_ProductManager**: Centralizes product information and management (option: example usage)

## Installation

### Step 1: Module setup

Place the following modules in your `ServerScriptService`:

1. `S_NexusServices` - Main service handler
2. `S_PurchaseServices` - Purchase processing service
3. `MS_NexusApiManager` - API management module
4. `MS_PlayerDataStore` - Data persistence module
5. `MS_ProductManager` - Product configuration module

### Step 2: RemoteEvents setup

Create the following RemoteEvents in `ReplicatedStorage`:

* `RE_ConfirmCreatorCode`
* `RE_UpdateCreatorCode` (used for both server-to-client and client-to-server)
* `RE_ClearCreatorCode`

### Step 3: API configuration

Update the API keys in `MS_NexusApiManager`:

```lua
-- Replace with your actual API keys
local headers = {["X-SHARED-SECRET"] = "nexus_pk_your_key_here"}
-- For attribution transactions
["X-SHARED-SECRET"] = "nexus_sk_your_key_here"
```

### Step 4: Product configuration

Configure your products in `MS_ProductManager`:

```lua
local products = {
    YourProduct = {
        id = 1234567890,  -- Your Roblox product ID
        price = 800,      -- Price in Robux
        name = "Your Product Name",
        creatorShare = false
    }
}
```

## API reference

### MS\_NexusApiManager

#### getCurrentTimestamp()

Returns the current UTC timestamp in ISO 8601 format.

```lua
local timestamp = MS_NexusApiManager.getCurrentTimestamp()
-- Returns: "2024-01-15T14:30:25Z"
```

#### getMemberByCode(player, memberCode, callback)

Validates a creator code and stores member data if valid.

**Parameters:**

* `player` (Player): The player object
* `memberCode` (string): The creator code to validate
* `callback` (function): Callback function with signature `(success, responseData)`

```lua
MS_NexusApiManager.getMemberByCode(player, "CREATOR123", function(success, data)
    if success then
        print("Valid creator code:", data)
    else
        warn("Invalid creator code")
    end
end)
```

#### makeAttributionTransaction(attributionData, callback)

Creates an attribution transaction in the Nexus system.

**Parameters:**

* `attributionData` (table): Transaction data
* `callback` (function): Callback function with signature `(success, responseData)`

**Attribution Data Structure:**

```lua
local attributionData = {
    memberId = "member-uuid",
    currency = "RBX",  -- Use "RBX" for Robux transactions
    description = "Product Name",
    subtotal = 800,    -- Amount in Robux (no conversion needed)
    transactionDate = "2024-01-15T14:30:25Z",
    transactionId = "unique-transaction-id"
}
```

### MS\_PlayerDataStore

#### savePlayerData(key, player, data)

Saves data for a specific player.

```lua
PlayerDataStoreModule.savePlayerData("Nexus_MemberData_", player, {
    memberCode = "CREATOR123",
    data = memberInfo
})
```

#### loadPlayerData(key, player)

Loads saved data for a player.

```lua
local data = PlayerDataStoreModule.loadPlayerData("Nexus_MemberData_", player)
if data then
    print("Member code:", data.memberCode)
end
```

#### clearPlayerData(key, player)

Removes saved data for a player.

```lua
PlayerDataStoreModule.clearPlayerData("Nexus_MemberData_", player)
```

### MS\_ProductManager

#### GetProductDetailsById(productId)

Retrieves product information by ID.

```lua
local product = ProductManager.GetProductDetailsById(1770107391)
if product then
    print("Product:", product.name, "Price:", product.price)
end
```

## Usage examples

### Basic creator code flow

```lua
-- Player enters creator code through UI
-- Client sends code to server via RemoteEvent
RE_ConfirmCreatorCode:FireServer("CREATOR123")

-- Server validates and stores the code
-- Success response sent back to client
-- UI updates to show confirmed creator
```

### Purchase flow with attribution

```lua
-- When a purchase is processed
local function processReceipt(receiptInfo)
    -- ... existing purchase logic ...
    
    -- Get stored member data
    local memberData = PlayerDataStoreModule.loadPlayerData("Nexus_MemberData_", player)
    
    if memberData then
        -- Create attribution transaction
        local attributionData = {
            memberId = memberData.data.id,
            currency = "RBX",  -- Direct Robux attribution
            description = productInfo.name,
            subtotal = productInfo.price,  -- Price in Robux
            transactionDate = MS_NexusApiManager.getCurrentTimestamp(),
            transactionId = receiptInfo.PurchaseId
        }
        
        MS_NexusApiManager.makeAttributionTransaction(attributionData, callback)
    end
end
```

## Configuration

### Currency handling

<Aside type="caution">
**Important Note**: The `MS_CurrencyConverter` module is deprecated. The Nexus API now supports direct Robux transactions using `"currency": "RBX"` in attribution data. This eliminates the need for server-side currency conversion.
</Aside>

Instead of converting Robux to USD:

```lua
-- OLD METHOD (deprecated)
local usdPrice = CurrencyConverter.ConvertRobuxToFormattedUsd(productInfo.price)
local attributionData = {
    currency = "USD",
    subtotal = usdPrice
}

-- NEW METHOD (recommended)
local attributionData = {
    currency = "RBX",
    subtotal = productInfo.price  -- Direct Robux amount
}
```

### API endpoints

The integration uses the following Nexus API endpoints.

<ApiMethod method="GET" path="/manage/members/{memberCode}" />

<LinkCard title="View full reference" description="Parameters, responses, and status codes." href="/api/operations/getmemberbycode/" />

<ApiMethod method="POST" path="/attributions/transactions" />

<LinkCard title="View full reference" description="Parameters, responses, and status codes." href="/api/operations/creatorattribution/" />

### Error handling

All API calls are wrapped in `pcall`:

```lua
local success, response = pcall(function()
    return HttpService:GetAsync(url, false, headers)
end)

if success then
    -- Handle successful response
else
    warn("API request failed:", response)
    -- Handle error case
end
```

## Best practices

### Security

* Store API keys securely and never expose them in client-side scripts
* Use separate public and secret keys for different operations
* Validate all user inputs before making API calls

### Performance

* Cache member data locally using DataStore to reduce API calls
* Implement proper error handling and retry logic
* Use pcall wrapping for all external service calls

### Data management

* Use consistent key prefixes for DataStore operations (`"Nexus_MemberData_"`)
* Implement data cleanup mechanisms for inactive players
* Consider data store request limits and implement queuing if necessary

## Troubleshooting

### Common issues

**Creator code not validating**

* Verify API keys are correct and active
* Check that the creator code exists in the Nexus system
* Ensure proper network connectivity

**Attribution transactions failing**

* Confirm the secret API key has transaction creation permissions
* Verify the member ID format matches Nexus requirements
* Check that all required fields are present in attribution data

**DataStore errors**

* Monitor DataStore request quotas
* Implement proper error handling for temporary failures
* Use UpdateAsync for operations that need to be atomic

### Debug information

Enable detailed logging by monitoring the console output:

```lua
-- Successful operations will print confirmation
print("Data saved for player: " .. player.Name)
print("Successfully created Nexus transaction")

-- Errors will generate warnings
warn("Failed to make a GET request: " .. tostring(response))
warn("Error saving data for " .. player.Name)
```

## Support

For additional support with the Nexus integration:

* Check the Nexus API documentation for endpoint specifications
* Monitor Roblox's DataStore service status for persistence issues
* Verify API key permissions in your Nexus dashboard
* Test with small user groups before full deployment

## Migration notes

If you're upgrading from a previous version that used currency conversion:

1. Remove dependencies on `MS_CurrencyConverter`
2. Update attribution transactions to use `"currency": "RBX"`
3. Pass Robux amounts directly without conversion
4. Test with small transactions to verify correct attribution
