Search code examples
objective-ctwilionsurlconnection

Retrieve All Recordings on Twilio Using Programable Voice SDK


I'm attempting to download all Recording objects associated with a Twilio account but do not see any methods in TwilioVoiceClient.h or VoiceClient.h that achieve this. I'm using the ProgramableVoice iOS SDK (beta 5), but the online documentation doesn't show any objective-c or Swift. I'm able to playback individual recordings with no problems if the Recording SID is known like so:

NSString *baseString = @"https://api.twilio.com/2010-04-01/Accounts/";
NSString *recordingSID = @"RExxxxxxxxxxxxxxxxxxxxxxxxxxxxx";    
NSURL *recordingUrl = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/Recordings/%@.mp3", baseString, kTwilAccount, recordingSID]];
avPlayer = [[AVPlayer alloc]initWithURL:recordingUrl];

What I'd like to do though, is download all associated recording objects for an account. For this, I've turned to NSUrlConnection:

NSString *baseStr = [NSString stringWithFormat:@"https://api.twilio.com/2010-04-01/Accounts/%@/Recordings.json", kTwilAccount];
NSURL *url = [NSURL URLWithString:baseStr];
NSMutableURLRequest *theRequest = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:1000.0];
NSString *authStr = [NSString stringWithFormat:@"%@:%@", kTwilAccount, authToken];
NSData *authData = [authStr dataUsingEncoding:NSASCIIStringEncoding];
NSString *authValue = [NSString stringWithFormat:@"Base %@", [authData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]];
[theRequest setValue:authValue forHTTPHeaderField:@"Authorization"];

[NSURLConnection sendAsynchronousRequest:theRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *responseCode, NSData *responseData, NSError *responseError) {
    if ([responseData length] > 0 && responseError == nil){
        // do work
    } else if ([responseData length] == 0 && responseError == nil){
        NSLog(@"data error: %@", responseError);

    } else if (responseError != nil && responseError.code == NSURLErrorTimedOut){
        NSLog(@"data timeout: %ld", (long)NSURLErrorTimedOut);


    } else if (responseError != nil){
        NSLog(@"data download error: %@", responseError);


    }
}];

This results in a download error with console output:

data download error: Error Domain=NSURLErrorDomain Code=-1012 "(null)" UserInfo={NSErrorFailingURLStringKey=https://api.twilio.com/2010-04-01/Accounts/ACdee27262ef5fd27a593a697d80e7f7b0/Recordings.json, NSUnderlyingError=0x17084aa70 {Error Domain=kCFErrorDomainCFNetwork Code=-1012 "(null)" UserInfo={_kCFURLErrorAuthFailedResponseKey={url = https://api.twilio.com/2010-04-01/Accounts/ACdeedkfdjieireijrekjrkejrk4kj4/Recordings.json}}}, NSErrorFailingURLKey=https://api.twilio.com/2010-04-01/Accounts/ACdeedkfdjieireijrekjrkejrk4kj4/Recordings.json}

Obviously, it either doesn't recognize the endpoint or doesn't like the way I'm authenticating. How should I be requesting this information in objective-c?

Thanks for reading.


Solution

  • Twilio developer evangelist here.

    We actually don't recommend that you put your account credentials into the application and make API calls from your application. It would be possible for a malicious attacker to decompile your application, retrieve your credentials and abuse your account.

    We recommend instead that you implement a server side solution to make the call to the API and retrieve your Recordings. Then you can communicate with your server from the application.

    Here's a blog post that explains more and includes an example for sending an SMS from an iOS application.