Sample code for 30+ languages & platforms
Lua Requires Chilkat v11.5.0+

Box: Poll User Events and Save a Checkpoint

See more Box Examples

Poll the authenticated user event stream in bounded batches. The local JSON checkpoint keeps processed event IDs and the next stream position. This single-process demonstration logs events; a production worker should commit its business action, deduplication record, and cursor transactionally and prune old IDs.

See the Box API guide for setup and the complete workflow.

Chilkat Lua Downloads

Lua
local chilkat = require("chilkat")

-- Requires Chilkat 11.5.0 or later and a previously unlocked Chilkat bundle.
-- See Global Unlock Sample.
-- Guide: Box API Guide.

local success = false

-- Supply an unexpired token obtained with one of the Box authentication examples.
-- A token represents a particular user or service account. IDs must be accessible to it.
local curl = chilkat.HttpCurl.new()
curl:set_var("access_token", "BOX_ACCESS_TOKEN")

local state = chilkat.JsonObject.new()
local files = chilkat.FileAccess.new()
local statePath = "qa_data/box_events_state.json"
if files:file_exists(statePath) then
    success = state:load_file(statePath)
    if not success then
        print(state.last_error_text)
        return
    end

    if not state:has_member("position") then
        print("Invalid checkpoint: position missing.")
        return
    end
else
    -- "now" starts a new subscription. It deliberately skips historical events.
    state:update_string("position", "now")
end

curl:set_var("position", state:string_of("position"))
local page = chilkat.JsonObject.new()
local seenPath = chilkat.StringBuilder.new()
local eventId = ""
local nextPosition = ""
local batch = 0
local i = 0
local count = 0
local more = true
while (more) and (batch < 20) do
    curl:clear_target_output("*")
    local authorizedCommand1 = chilkat.StringBuilder.new()
    authorizedCommand1:set_string("curl -X GET \"https://api.box.com/2.0/events?stream_type=all&stream_position={{position}}&limit=100\" -H \"Authorization: Bearer {{access_token}}\"")
    local headerReplacement1 = authorizedCommand1:replace("{{access_token}}", curl:get_var("access_token"))
    success = curl:do_your_thing(authorizedCommand1:get_as_string())
    if (not success) or (curl.status_code ~= 200) then
        print("Box request failed. HTTP status: " .. curl.status_code)
        print("Failure reason: " .. curl.fail_reason)
        print(curl.response_body_str)
        return
    end

    success = curl:get_response_json(page)
    if not success then
        print(curl.last_error_text)
        return
    end

    count = page:size_of_array("entries")
    i = 0
    while i < count do
        page.i = i
        eventId = page:string_of("entries[i].event_id")
        if eventId == "" then
            print("Event without an event_id; checkpoint not advanced.")
            return
        end

        seenPath:clear()
        seenPath:append("seen.")
        seenPath:append(eventId)
        if not state:has_member(seenPath:get_as_string()) then
            -- Replace this logging with your idempotent business operation.
            -- Record success only after that operation succeeds.
            print(eventId .. " " .. page:string_of("entries[i].event_type") .. " " .. page:string_of("entries[i].source.id"))
            state:update_bool(seenPath:get_as_string(), true)
        end

        i = i + 1
    end

    nextPosition = page:string_of("next_stream_position")
    if nextPosition == "" then
        print("Missing next_stream_position; checkpoint not advanced.")
        return
    end

    more = (count > 0) and (nextPosition ~= curl:get_var("position"))
    state:update_string("position", nextPosition)
    success = state:write_file(statePath)
    if not success then
        print(state.last_error_text)
        return
    end

    curl:set_var("position", nextPosition)
    batch = batch + 1
end

print("Checkpoint saved. Run again later to continue polling.")