private function initConfig($config)
    {
        $specifiedConfig = array_replace_recursive($this->clientConfig, $config);
        if (!isset($specifiedConfig['apiVersion'])) {
            trigger_error(Client::NO_API_VERSION_WARNING, E_USER_DEPRECATED);
        }

        $newConfig = array_replace_recursive($this->defaultConfig, $specifiedConfig);
        $apiVersion = str_replace('#^v#', '', $newConfig['apiVersion']);
        $projectBased = $newConfig['useProjectHostname'];
        $useCdn = isset($newConfig['useCdn']) ? $newConfig['useCdn'] : false;
        $projectId = isset($newConfig['projectId']) ? $newConfig['projectId'] : null;
        $dataset = isset($newConfig['dataset']) ? $newConfig['dataset'] : null;

        if (preg_match('#^\d{4}-\d{2}-\d{2}$#', $apiVersion)) {
            $apiDate = new DateTimeImmutable($apiVersion, new DateTimeZone('UTC'));
            $currentDate = new DateTimeImmutable('now', new DateTimeZone('UTC'));
            $currentDate = $currentDate->setTime(0, 0, 0);
            $tomorrow = $currentDate->add(new DateInterval('P01D'));

            if ($apiVersion === $tomorrow->format('Y-m-d')) {
                // The date specified is actually "tomorrow" in UTC terms, which is _allowed_,
                // but might suddenly change behavior. Warn that the user probably wants to use
                // todays UTC date, unless she means to use a hotfix (just released) version
                trigger_error(sprintf(
                    self::TOMORROW_API_VERSION_WARNING,
                    $currentDate->format('Y-m-d'),
                    $apiVersion,
                    $currentDate->format('Y-m-d')
                ), E_USER_WARNING);
            } elseif ($apiDate > $tomorrow) {
                // The date specified is in the future, which the API will reject. Since you will
                // not be able to use the API for anything, throwing is the only logical choice
                throw new ConfigException(sprintf(
                    self::FUTURE_API_VERSION_ERROR,
                    $currentDate->format('Y-m-d'),
                    $apiVersion,
                    $currentDate->format('Y-m-d')
                ));
            }
        }

        if ($projectBased && !$projectId) {
            throw new ConfigException('Configuration must contain `projectId`');
        }

        if ($projectBased && !$dataset) {
            throw new ConfigException('Configuration must contain `dataset`');
        }

        if ($useCdn && !empty($newConfig['token'])) {
            throw new ConfigException(
                'Cannot combine `useCdn` option with `token` as authenticated requests cannot be cached'
            );
        }

        $hostParts = explode('://', $newConfig['apiHost']);
        $protocol = $hostParts[0];
        $host = $hostParts[1];

        if ($projectBased) {
            $newConfig['url'] = $protocol . '://' . $projectId . '.' . $host . '/v' . $apiVersion;
        } else {
            $newConfig['url'] = $newConfig['apiHost'] . '/v' . $apiVersion;
        }

        $newConfig['useCdn'] = $useCdn;
        $newConfig['cdnUrl'] = preg_replace('#(/|\.)api.sanity.io/#', '$1apicdn.sanity.io/', $newConfig['url']);
        return $newConfig;
    }