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

Objective-C
#import <CkoHttpCurl.h>
#import <CkoJsonObject.h>
#import <CkoFileAccess.h>
#import <NSString.h>
#import <CkoStringBuilder.h>

BOOL success = NO;

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

success = NO;

//  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.
CkoHttpCurl *curl = [[CkoHttpCurl alloc] init];
[curl SetVar: @"access_token" varValue: @"BOX_ACCESS_TOKEN"];

CkoJsonObject *state = [[CkoJsonObject alloc] init];
CkoFileAccess *files = [[CkoFileAccess alloc] init];
NSString *statePath = @"qa_data/box_events_state.json";
if ([files FileExists: statePath] == YES) {
    success = [state LoadFile: statePath];
    if (success != YES) {
        NSLog(@"%@",state.LastErrorText);
        return;
    }

    if ([state HasMember: @"position"] != YES) {
        NSLog(@"%@",@"Invalid checkpoint: position missing.");
        return;
    }

}
else {
    //  "now" starts a new subscription. It deliberately skips historical events.
    [state UpdateString: @"position" value: @"now"];
}

[curl SetVar: @"position" varValue: [state StringOf: @"position"]];
CkoJsonObject *page = [[CkoJsonObject alloc] init];
CkoStringBuilder *seenPath = [[CkoStringBuilder alloc] init];
NSString *eventId = 0;
NSString *nextPosition = 0;
int batch = 0;
int i;
int count;
BOOL more = YES;
while ((more == YES) && (batch < 20)) {
    [curl ClearTargetOutput: @"*"];
    CkoStringBuilder *authorizedCommand1 = [[CkoStringBuilder alloc] init];
    [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}}\""];
    int headerReplacement1 = [[authorizedCommand1 Replace: @"{{access_token}}" replacement: [curl GetVar: @"access_token"]] intValue];
    success = [curl DoYourThing: [authorizedCommand1 GetAsString]];
    if ((success != YES) || ([curl.StatusCode intValue] != 200)) {
        NSLog(@"%@%d",@"Box request failed. HTTP status: ",[curl.StatusCode intValue]);
        NSLog(@"%@%d",@"Failure reason: ",[curl.FailReason intValue]);
        NSLog(@"%@",curl.ResponseBodyStr);
        return;
    }

    success = [curl GetResponseJson: page];
    if (success != YES) {
        NSLog(@"%@",curl.LastErrorText);
        return;
    }

    count = [[page SizeOfArray: @"entries"] intValue];
    i = 0;
    while (i < count) {
        page.I = [NSNumber numberWithInt: i];
        eventId = [page StringOf: @"entries[i].event_id"];
        if (eventId == @"") {
            NSLog(@"%@",@"Event without an event_id; checkpoint not advanced.");
            return;
        }

        [seenPath Clear];
        [seenPath Append: @"seen."];
        [seenPath Append: eventId];
        if ([state HasMember: [seenPath GetAsString]] == NO) {
            //  Replace this logging with your idempotent business operation.
            //  Record success only after that operation succeeds.
            NSLog(@"%@%@%@%@%@",eventId,@" ",[page StringOf: @"entries[i].event_type"],@" ",[page StringOf: @"entries[i].source.id"]);
            [state UpdateBool: [seenPath GetAsString] value: YES];
        }

        i = i + 1;
    }

    nextPosition = [page StringOf: @"next_stream_position"];
    if (nextPosition == @"") {
        NSLog(@"%@",@"Missing next_stream_position; checkpoint not advanced.");
        return;
    }

    more = (count > 0) && (nextPosition != [curl GetVar: @"position"]);
    [state UpdateString: @"position" value: nextPosition];
    success = [state WriteFile: statePath];
    if (success != YES) {
        NSLog(@"%@",state.LastErrorText);
        return;
    }

    [curl SetVar: @"position" varValue: nextPosition];
    batch = batch + 1;
}

NSLog(@"%@",@"Checkpoint saved. Run again later to continue polling.");