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

PowerBuilder
integer li_rc
long li_Success
oleobject loo_Curl
oleobject loo_State
oleobject loo_Files
string ls_StatePath
oleobject loo_Page
oleobject loo_SeenPath
string ls_EventId
string ls_NextPosition
long li_Batch
long i
long li_Count
long li_More
oleobject loo_AuthorizedCommand1
long li_HeaderReplacement1

li_Success = 0

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

li_Success = 0

//  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.
loo_Curl = create oleobject
li_rc = loo_Curl.ConnectToNewObject("Chilkat.HttpCurl")
if li_rc < 0 then
    destroy loo_Curl
    MessageBox("Error","Connecting to COM object failed")
    return
end if
loo_Curl.SetVar("access_token","BOX_ACCESS_TOKEN")

loo_State = create oleobject
li_rc = loo_State.ConnectToNewObject("Chilkat.JsonObject")

loo_Files = create oleobject
li_rc = loo_Files.ConnectToNewObject("Chilkat.FileAccess")

ls_StatePath = "qa_data/box_events_state.json"
if loo_Files.FileExists(ls_StatePath) = 1 then
    li_Success = loo_State.LoadFile(ls_StatePath)
    if li_Success <> 1 then
        Write-Debug loo_State.LastErrorText
        destroy loo_Curl
        destroy loo_State
        destroy loo_Files
        return
    end if

    if loo_State.HasMember("position") <> 1 then
        Write-Debug "Invalid checkpoint: position missing."
        destroy loo_Curl
        destroy loo_State
        destroy loo_Files
        return
    end if

else
    //  "now" starts a new subscription. It deliberately skips historical events.
    loo_State.UpdateString("position","now")
end if

loo_Curl.SetVar("position",loo_State.StringOf("position"))
loo_Page = create oleobject
li_rc = loo_Page.ConnectToNewObject("Chilkat.JsonObject")

loo_SeenPath = create oleobject
li_rc = loo_SeenPath.ConnectToNewObject("Chilkat.StringBuilder")

li_Batch = 0

li_More = 1
do while (li_More = 1) AND (li_Batch < 20)
    loo_Curl.ClearTargetOutput("*")
    loo_AuthorizedCommand1 = create oleobject
    li_rc = loo_AuthorizedCommand1.ConnectToNewObject("Chilkat.StringBuilder")

    loo_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}}~"")
    li_HeaderReplacement1 = loo_AuthorizedCommand1.Replace("{{access_token}}",loo_Curl.GetVar("access_token"))
    li_Success = loo_Curl.DoYourThing(loo_AuthorizedCommand1.GetAsString())
    if (li_Success <> 1) OR (loo_Curl.StatusCode <> 200) then
        Write-Debug "Box request failed. HTTP status: " + string(loo_Curl.StatusCode)
        Write-Debug "Failure reason: " + string(loo_Curl.FailReason)
        Write-Debug loo_Curl.ResponseBodyStr
        destroy loo_Curl
        destroy loo_State
        destroy loo_Files
        destroy loo_Page
        destroy loo_SeenPath
        destroy loo_AuthorizedCommand1
        return
    end if

    li_Success = loo_Curl.GetResponseJson(loo_Page)
    if li_Success <> 1 then
        Write-Debug loo_Curl.LastErrorText
        destroy loo_Curl
        destroy loo_State
        destroy loo_Files
        destroy loo_Page
        destroy loo_SeenPath
        destroy loo_AuthorizedCommand1
        return
    end if

    li_Count = loo_Page.SizeOfArray("entries")
    i = 0
    do while i < li_Count
        loo_Page.I = i
        ls_EventId = loo_Page.StringOf("entries[i].event_id")
        if ls_EventId = "" then
            Write-Debug "Event without an event_id; checkpoint not advanced."
            destroy loo_Curl
            destroy loo_State
            destroy loo_Files
            destroy loo_Page
            destroy loo_SeenPath
            destroy loo_AuthorizedCommand1
            return
        end if

        loo_SeenPath.Clear()
        loo_SeenPath.Append("seen.")
        loo_SeenPath.Append(ls_EventId)
        if loo_State.HasMember(loo_SeenPath.GetAsString()) = 0 then
            //  Replace this logging with your idempotent business operation.
            //  Record success only after that operation succeeds.
            Write-Debug ls_EventId + " " + loo_Page.StringOf("entries[i].event_type") + " " + loo_Page.StringOf("entries[i].source.id")
            loo_State.UpdateBool(loo_SeenPath.GetAsString(),1)
        end if

        i = i + 1
    loop
    ls_NextPosition = loo_Page.StringOf("next_stream_position")
    if ls_NextPosition = "" then
        Write-Debug "Missing next_stream_position; checkpoint not advanced."
        destroy loo_Curl
        destroy loo_State
        destroy loo_Files
        destroy loo_Page
        destroy loo_SeenPath
        destroy loo_AuthorizedCommand1
        return
    end if

    li_More = (li_Count > 0) AND (ls_NextPosition <> loo_Curl.GetVar("position"))
    loo_State.UpdateString("position",ls_NextPosition)
    li_Success = loo_State.WriteFile(ls_StatePath)
    if li_Success <> 1 then
        Write-Debug loo_State.LastErrorText
        destroy loo_Curl
        destroy loo_State
        destroy loo_Files
        destroy loo_Page
        destroy loo_SeenPath
        destroy loo_AuthorizedCommand1
        return
    end if

    loo_Curl.SetVar("position",ls_NextPosition)
    li_Batch = li_Batch + 1
loop
Write-Debug "Checkpoint saved. Run again later to continue polling."


destroy loo_Curl
destroy loo_State
destroy loo_Files
destroy loo_Page
destroy loo_SeenPath
destroy loo_AuthorizedCommand1