Home Docs Lua

Lua Quick Start

Integrate Indieop API into your Lua games using LÖVE, Corona, or Defold.

Prerequisites

Before you begin, make sure you have:

  1. Created an Indieop account
  2. Created a game and obtained your API key from the game settings
  3. Installed a JSON library for Lua (most frameworks include one)

Overview

This guide shows you how to send player feedback and form submissions from your Lua game to the Indieop API. Compatible with:

  • LÖVE (Love2D): Using socket.http library
  • Corona SDK: Using network.request
  • Defold: Using http.request

LÖVE (Love2D) Implementation

Step 1: Install Dependencies

First, ensure you have LuaSocket and a JSON library. For LÖVE, you can use the built-in or add these libraries to your project.

Step 2: Create the API Client

Create a new file called indieop.lua:

-- indieop.lua
local https = require("https")
local json = require("json") -- or dkjson, cjson, etc.

local IndieOp = {}
IndieOp.__index = IndieOp

function IndieOp:new(apiKey)
    local client = {
        apiKey = apiKey,
        baseURL = "https://indieop.com/api/sdk"
    }
    setmetatable(client, IndieOp)
    return client
end

function IndieOp:submitForm(submissionData, callback)
    local url = self.baseURL .. "/submit"
    local jsonData = json.encode(submissionData)
    
    local headers = {
        ["Content-Type"] = "application/json",
        ["X-API-Key"] = self.apiKey,
        ["Content-Length"] = tostring(#jsonData)
    }
    
    https.request(url, {
        method = "POST",
        headers = headers,
        body = jsonData
    }, function(code, body, headers)
        if code == 200 or code == 201 then
            local response = json.decode(body)
            print("Submission successful: " .. response.message)
            if callback then callback(true, response) end
        else
            local errorResponse = json.decode(body)
            print("Submission failed: " .. errorResponse.message)
            if callback then callback(false, errorResponse) end
        end
    end)
end

function IndieOp:createField(key, label, fieldType, value, options)
    local field = {
        key = key,
        label = label,
        type = fieldType,
        value = value
    }
    if options then
        field.options = options
    end
    return field
end

return IndieOp

Step 3: Use the Client in Your Game

Here's how to use it in your LÖVE game:

-- main.lua
local IndieOp = require("indieop")
local client = IndieOp:new("your_game_api_key_here")

local feedbackSubmitted = false

function love.load()
    -- Game initialization
    love.window.setTitle("My Awesome Game")
end

function submitPlayerFeedback(rating, comments)
    local submission = {
        form_name = "Player Feedback",
        tag = "feedback",
        form_type = "feedback",
        player_identifier = love.system.getOS() .. "_player",
        game_version = "1.0.0",
        fields = {
            client:createField("rating", "Overall Rating", "rating", rating),
            client:createField("comments", "Your Feedback", "text", comments),
            client:createField("enjoyed", "Did you enjoy?", "checkbox", true)
        }
    }
    
    client:submitForm(submission, function(success, response)
        if success then
            print("Thank you for your feedback!")
            feedbackSubmitted = true
        else
            print("Failed to submit feedback. Please try again.")
        end
    end)
end

function love.keypressed(key)
    if key == "f" then
        -- Submit feedback when player presses 'F'
        submitPlayerFeedback(5, "This game is amazing!")
    end
end

function love.draw()
    love.graphics.print("Press 'F' to submit feedback", 10, 10)
    if feedbackSubmitted then
        love.graphics.print("Feedback submitted! Thank you!", 10, 30)
    end
end

Corona SDK Implementation

Corona SDK has built-in network support. Create indieop.lua:

-- indieop.lua (Corona SDK)
local json = require("json")

local IndieOp = {}
IndieOp.__index = IndieOp

function IndieOp:new(apiKey)
    local client = {
        apiKey = apiKey,
        baseURL = "https://indieop.com/api/sdk"
    }
    setmetatable(client, IndieOp)
    return client
end

function IndieOp:submitForm(submissionData, callback)
    local url = self.baseURL .. "/submit"
    
    local headers = {
        ["Content-Type"] = "application/json",
        ["X-API-Key"] = self.apiKey
    }
    
    local params = {
        headers = headers,
        body = json.encode(submissionData)
    }
    
    local function networkListener(event)
        if event.isError then
            print("Network error: " .. event.response)
            if callback then callback(false, nil) end
        else
            local response = json.decode(event.response)
            
            if event.status == 200 or event.status == 201 then
                print("Submission successful!")
                if callback then callback(true, response) end
            else
                print("Submission failed: " .. response.message)
                if callback then callback(false, response) end
            end
        end
    end
    
    network.request(url, "POST", networkListener, params)
end

function IndieOp:createField(key, label, fieldType, value, options)
    local field = {
        key = key,
        label = label,
        type = fieldType,
        value = value
    }
    if options then
        field.options = options
    end
    return field
end

return IndieOp

Usage in Corona SDK

-- main.lua (Corona SDK)
local IndieOp = require("indieop")
local client = IndieOp:new("your_game_api_key_here")

local function submitBugReport(description)
    local submission = {
        form_name = "Bug Report",
        tag = "bugs",
        form_type = "bug_report",
        player_identifier = system.getInfo("deviceID"),
        game_version = "1.0.0",
        repository_version = "main@abc123",
        fields = {
            client:createField("description", "Bug Description", "text", description),
            client:createField("severity", "Severity", "dropdown", "Medium", 
                {"Low", "Medium", "High", "Critical"}),
            client:createField("reproducible", "Can Reproduce?", "checkbox", true)
        }
    }
    
    client:submitForm(submission, function(success, response)
        if success then
            native.showAlert("Thank You", "Bug report submitted successfully!", {"OK"})
        else
            native.showAlert("Error", "Failed to submit bug report", {"OK"})
        end
    end)
end

-- Example: Submit bug report when button is tapped
local submitButton = display.newText({
    text = "Report Bug",
    x = display.contentCenterX,
    y = display.contentCenterY,
    font = native.systemFont,
    fontSize = 24
})

submitButton:addEventListener("tap", function()
    submitBugReport("Player character gets stuck in wall at level 2")
end)

Defold Implementation

Defold uses its own HTTP module. Create indieop.lua:

-- indieop.lua (Defold)
local M = {}

M.api_key = nil
M.base_url = "https://indieop.com/api/sdk"

function M.init(api_key)
    M.api_key = api_key
end

function M.submit_form(submission_data, callback)
    local url = M.base_url .. "/submit"
    local json_data = json.encode(submission_data)
    
    local headers = {
        ["Content-Type"] = "application/json",
        ["X-API-Key"] = M.api_key
    }
    
    http.request(url, "POST", function(self, id, response)
        if response.status == 200 or response.status == 201 then
            local result = json.decode(response.response)
            print("Submission successful: " .. result.message)
            if callback then callback(true, result) end
        else
            local error_result = json.decode(response.response)
            print("Submission failed: " .. error_result.message)
            if callback then callback(false, error_result) end
        end
    end, headers, json_data)
end

function M.create_field(key, label, field_type, value, options)
    local field = {
        key = key,
        label = label,
        type = field_type,
        value = value
    }
    if options then
        field.options = options
    end
    return field
end

return M

Usage in Defold

-- feedback_script.script (Defold)
local indieop = require("indieop")

function init(self)
    -- Initialize the client
    indieop.init("your_game_api_key_here")
end

function submit_feedback(rating, comments, difficulty)
    local submission = {
        form_name = "Player Feedback",
        tag = "feedback",
        form_type = "feedback",
        player_identifier = sys.get_sys_info().device_ident,
        game_version = sys.get_config("project.version"),
        fields = {
            indieop.create_field("rating", "Overall Rating", "rating", rating),
            indieop.create_field("comments", "Comments", "text", comments),
            indieop.create_field("difficulty", "Difficulty", "dropdown", difficulty,
                {"Easy", "Medium", "Hard"})
        }
    }
    
    indieop.submit_form(submission, function(success, response)
        if success then
            print("Feedback submitted successfully!")
            -- Update UI to show success
        else
            print("Failed to submit feedback")
            -- Show error message
        end
    end)
end

function on_message(self, message_id, message, sender)
    if message_id == hash("submit_feedback") then
        submit_feedback(message.rating, message.comments, message.difficulty)
    end
end

Field Types Reference

The Indieop API supports four field types:

Field Type Lua Type Example
text string "Great game!"
rating number (1-5) 5
checkbox boolean true
dropdown string (from options) "Medium"

Error Handling

Always handle errors gracefully in your game:

local failedSubmissions = {}

local function storeFailedSubmission(data)
    table.insert(failedSubmissions, {
        data = data,
        timestamp = os.time()
    })
    print("Submission stored locally for retry")
end

local function submitWithRetry(client, submission, maxRetries)
    maxRetries = maxRetries or 3
    local attempts = 0
    
    local function attemptSubmit()
        attempts = attempts + 1
        
        client:submitForm(submission, function(success, response)
            if success then
                print("Submission successful after " .. attempts .. " attempts")
            elseif attempts < maxRetries then
                print("Attempt " .. attempts .. " failed, retrying...")
                -- Wait and retry
                timer.performWithDelay(1000 * attempts, attemptSubmit)
            else
                print("All retry attempts failed")
                storeFailedSubmission(submission)
            end
        end)
    end
    
    attemptSubmit()
end

-- Retry failed submissions later
local function retryFailedSubmissions(client)
    for i = #failedSubmissions, 1, -1 do
        local item = failedSubmissions[i]
        
        client:submitForm(item.data, function(success, response)
            if success then
                table.remove(failedSubmissions, i)
                print("Successfully submitted queued submission")
            end
        end)
    end
end

Best Practices

  • Store API key securely: Don't hardcode it in version control
  • Handle network errors: Implement retry logic and offline queueing
  • Validate data locally: Check field values before sending
  • Rate limiting: Don't exceed 100 requests per minute
  • Use appropriate JSON library: Different Lua environments have different JSON libraries
  • Test thoroughly: Test both success and failure cases

Next Steps