function createApiKey(array $keyDetails)
{
    $api = new AVRSAPI();
    $api->setMethod('POST');
    $api->setURL('/api/v1.5/apiauthkeys/');
    foreach ($keyDetails as $key => $value) {
        $api->addPayload($key, $value);
    }
    $api->send();
    $httpInfo = $api->getInfo();
    $results = json_decode($api->getResult(), true);
    if ($httpInfo['http_code'] != 200) {
        print_r($results);
        throw new \Exception('Unable to create API key.  Received http error code: ' . $httpInfo['http_code']);
    }
    if (isset($results['keys'][0]) && is_array($results['keys'][0])) {
        return $results['keys'][0];
    }
    return [];
}
// check from newest reservation to oldest
$haveReservation = false;
$reservations = array_reverse(TestRecords::getRecords());
foreach ($reservations as $reservation) {
    if (($reservation['conditions'] & $bitmask) == $bitmask) {
        $haveReservation = true;
        break;
    }
}
if (!$haveReservation) {
    $reservation = TestRecords::reserveRecord($bitmask);
}
// create a deal with the required fields and immediately request fees
$api = new AVRSAPI();
$api->setURL('/api/v1/deals/');
$api->setMethod('POST');
$api->addPayload('vehicles', array(array('vin' => $reservation['vin'], 'plate' => $reservation['plate'], 'insurance' => 'Y')));
$api->addPayload('status', 'QF');
$api->addPayload('transaction-type', 6);
$api->send();
$response = json_decode($api->getResult(), true);
while ($retryAttempts++ < $retryMax && $response['deals'][0]['error-code'] == 'CADMV/Q023') {
    error_log('DMV Retry Code Encountered');
    sleep($retryDelayBase * pow(2, $retryAttempts));
    $api->send();
    $response = json_decode($api->getResult(), true);
}
Writer::writeRequestResponse($api);
if (empty($response['deals'][0]['error-code'])) {
    sleep(1);
    // just to be sure that we don't overwrite the first request/response pair
use api\AVRSAPI;
use api\TestRecords;
// exponential backoff settings
$retryAttempts = 0;
$retryMax = 3;
$retryDelayBase = 3;
// create a deal with the required fields, request fees after getting a deal with decoded vin info back
$api = new AVRSAPI();
$api->setURL('/api/v1/deals/');
$api->setMethod('POST');
$api->addPayload('owners', [['zip' => 95492]]);
$api->addPayload('vehicles', [['cost' => 45000, 'first-operated-date' => '2017-11-11', 'first-sold-date' => '2017-11-11', 'vin' => '3B7HC13YXYG105749', 'type-license-code' => 11]]);
$api->addPayload('transaction-type', 3);
$api->addPayload('gateway-type', 'CALC-CA');
$api->send();
$response = json_decode($api->getResult(), true);
Writer::writeRequestResponse($api);
$api = new AVRSAPI();
$api->setURL('/api/v1/deals/');
$api->setMethod('PUT');
$api->addPayload('status', 'QF');
$api->addPayload('id', $response['deals'][0]['id']);
$api->send();
$response = json_decode($api->getResult(), true);
while ($retryAttempts++ < $retryMax && $response['deals'][0]['error-code'] == 'CADMV/Q023') {
    error_log('DMV Retry Code Encountered');
    sleep($retryDelayBase * pow(2, $retryAttempts));
    $api->send();
    $response = json_decode($api->getResult(), true);
}
Writer::writeRequestResponse($api);