Sample code for 30+ languages & platforms
Ruby 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 Ruby Downloads

Ruby
require 'chilkat'

success = false

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

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.
curl = Chilkat::CkHttpCurl.new()
curl.SetVar("access_token","BOX_ACCESS_TOKEN")

state = Chilkat::CkJsonObject.new()
files = Chilkat::CkFileAccess.new()
statePath = "qa_data/box_events_state.json"
if (files.FileExists(statePath) == true)
    success = state.LoadFile(statePath)
    if (success != true)
        print state.lastErrorText() + "\n";
        exit
    end

    if (state.HasMember("position") != true)
        print "Invalid checkpoint: position missing." + "\n";
        exit
    end

else
    #  "now" starts a new subscription. It deliberately skips historical events.
    state.UpdateString("position","now")
end

curl.SetVar("position",state.stringOf("position"))
page = Chilkat::CkJsonObject.new()
seenPath = Chilkat::CkStringBuilder.new()

batch = 0

more = true
while (more == true) and (batch < 20)
    curl.ClearTargetOutput("*")
    authorizedCommand1 = Chilkat::CkStringBuilder.new()
    authorizedCommand1.SetString("curl -X GET \"https://api.box.com/2.0/events?stream_type=all&stream_position={{position}}&limit=100\" -H \"Authorization: Bearer {{access_token}}\"")
    headerReplacement1 = authorizedCommand1.Replace("{{access_token}}",curl.getVar("access_token"))
    success = curl.DoYourThing(authorizedCommand1.getAsString())
    if ((success != true) or (curl.get_StatusCode() != 200))
        print "Box request failed. HTTP status: " + curl.get_StatusCode().to_s() + "\n";
        print "Failure reason: " + curl.get_FailReason().to_s() + "\n";
        print curl.responseBodyStr() + "\n";
        exit
    end

    success = curl.GetResponseJson(page)
    if (success != true)
        print curl.lastErrorText() + "\n";
        exit
    end

    count = page.SizeOfArray("entries")
    i = 0
    while i < count
        page.put_I(i)
        eventId = page.stringOf("entries[i].event_id")
        if (eventId == "")
            print "Event without an event_id; checkpoint not advanced." + "\n";
            exit
        end

        seenPath.Clear()
        seenPath.Append("seen.")
        seenPath.Append(eventId)
        if (state.HasMember(seenPath.getAsString()) == false)
            #  Replace this logging with your idempotent business operation.
            #  Record success only after that operation succeeds.
            print eventId + " " + page.stringOf("entries[i].event_type") + " " + page.stringOf("entries[i].source.id") + "\n";
            state.UpdateBool(seenPath.getAsString(),true)
        end

        i = i + 1
    end
    nextPosition = page.stringOf("next_stream_position")
    if (nextPosition == "")
        print "Missing next_stream_position; checkpoint not advanced." + "\n";
        exit
    end

    more = (count > 0) and (nextPosition != curl.getVar("position"))
    state.UpdateString("position",nextPosition)
    success = state.WriteFile(statePath)
    if (success != true)
        print state.lastErrorText() + "\n";
        exit
    end

    curl.SetVar("position",nextPosition)
    batch = batch + 1
end
print "Checkpoint saved. Run again later to continue polling." + "\n";