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

Delphi DLL
var
success: Boolean;
curl: HCkHttpCurl;
state: HCkJsonObject;
files: HCkFileAccess;
statePath: PWideChar;
page: HCkJsonObject;
seenPath: HCkStringBuilder;
eventId: PWideChar;
nextPosition: PWideChar;
batch: Integer;
i: Integer;
count: Integer;
more: Boolean;
authorizedCommand1: HCkStringBuilder;
headerReplacement1: Integer;

begin
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 := CkHttpCurl_Create();
CkHttpCurl_SetVar(curl,'access_token','BOX_ACCESS_TOKEN');

state := CkJsonObject_Create();
files := CkFileAccess_Create();
statePath := 'qa_data/box_events_state.json';
if (CkFileAccess_FileExists(files,statePath) = True) then
  begin
    success := CkJsonObject_LoadFile(state,statePath);
    if (success <> True) then
      begin
        Memo1.Lines.Add(CkJsonObject__lastErrorText(state));
        Exit;
      end;
    if (CkJsonObject_HasMember(state,'position') <> True) then
      begin
        Memo1.Lines.Add('Invalid checkpoint: position missing.');
        Exit;
      end;
  end
else
  begin
    //  "now" starts a new subscription. It deliberately skips historical events.
    CkJsonObject_UpdateString(state,'position','now');
  end;
CkHttpCurl_SetVar(curl,'position',CkJsonObject__stringOf(state,'position'));
page := CkJsonObject_Create();
seenPath := CkStringBuilder_Create();

batch := 0;

more := True;
while (more = True) and (batch < 20) do
  begin
    CkHttpCurl_ClearTargetOutput(curl,'*');
    authorizedCommand1 := CkStringBuilder_Create();
    CkStringBuilder_SetString(authorizedCommand1,'curl -X GET "https://api.box.com/2.0/events?stream_type=all&stream_position={{position}}&limit=100" -H "Authorization: Bearer {{access_token}}"');
    headerReplacement1 := CkStringBuilder_Replace(authorizedCommand1,'{{access_token}}',CkHttpCurl__getVar(curl,'access_token'));
    success := CkHttpCurl_DoYourThing(curl,CkStringBuilder__getAsString(authorizedCommand1));
    if ((success <> True) or (CkHttpCurl_getStatusCode(curl) <> 200)) then
      begin
        Memo1.Lines.Add('Box request failed. HTTP status: ' + IntToStr(CkHttpCurl_getStatusCode(curl)));
        Memo1.Lines.Add('Failure reason: ' + IntToStr(CkHttpCurl_getFailReason(curl)));
        Memo1.Lines.Add(CkHttpCurl__responseBodyStr(curl));
        Exit;
      end;
    success := CkHttpCurl_GetResponseJson(curl,page);
    if (success <> True) then
      begin
        Memo1.Lines.Add(CkHttpCurl__lastErrorText(curl));
        Exit;
      end;
    count := CkJsonObject_SizeOfArray(page,'entries');
    i := 0;
    while i < count do
      begin
        CkJsonObject_putI(page,i);
        eventId := CkJsonObject__stringOf(page,'entries[i].event_id');
        if (eventId = '') then
          begin
            Memo1.Lines.Add('Event without an event_id; checkpoint not advanced.');
            Exit;
          end;
        CkStringBuilder_Clear(seenPath);
        CkStringBuilder_Append(seenPath,'seen.');
        CkStringBuilder_Append(seenPath,eventId);
        if (CkJsonObject_HasMember(state,CkStringBuilder__getAsString(seenPath)) = False) then
          begin
            //  Replace this logging with your idempotent business operation.
            //  Record success only after that operation succeeds.
            Memo1.Lines.Add(eventId + ' ' + CkJsonObject__stringOf(page,'entries[i].event_type') + ' ' + CkJsonObject__stringOf(page,'entries[i].source.id'));
            CkJsonObject_UpdateBool(state,CkStringBuilder__getAsString(seenPath),True);
          end;
        i := i + 1;
      end;

    nextPosition := CkJsonObject__stringOf(page,'next_stream_position');
    if (nextPosition = '') then
      begin
        Memo1.Lines.Add('Missing next_stream_position; checkpoint not advanced.');
        Exit;
      end;
    more := (count > 0) and (nextPosition <> CkHttpCurl__getVar(curl,'position'));
    CkJsonObject_UpdateString(state,'position',nextPosition);
    success := CkJsonObject_WriteFile(state,statePath);
    if (success <> True) then
      begin
        Memo1.Lines.Add(CkJsonObject__lastErrorText(state));
        Exit;
      end;
    CkHttpCurl_SetVar(curl,'position',nextPosition);
    batch := batch + 1;
  end;

Memo1.Lines.Add('Checkpoint saved. Run again later to continue polling.');

CkHttpCurl_Dispose(curl);
CkJsonObject_Dispose(state);
CkFileAccess_Dispose(files);
CkJsonObject_Dispose(page);
CkStringBuilder_Dispose(seenPath);
    CkStringBuilder_Dispose(authorizedCommand1);