diff --git a/api-sdk-php/.travis.yml b/api-sdk-php/.travis.yml
index efbf666..9b8a8e8 100644
--- a/api-sdk-php/.travis.yml
+++ b/api-sdk-php/.travis.yml
@@ -15,3 +15,4 @@ script: vendor/bin/phpunit --coverage-text --debug --verbose --testsuite unit
 notifications:
   email:
     - pratushnyi@smartling.com
+    - ploparev@smartling.com
diff --git a/api-sdk-php/examples/context-example.php b/api-sdk-php/examples/context-example.php
index fb71e99..5d594da 100644
--- a/api-sdk-php/examples/context-example.php
+++ b/api-sdk-php/examples/context-example.php
@@ -12,6 +12,7 @@ error_reporting(E_ALL);
  */
 
 use Smartling\Context\Params\UploadContextParameters;
+use Smartling\Context\Params\UploadResourceParameters;
 
 $longOpts = [
     'project-id:',
@@ -50,7 +51,7 @@ $authProvider = \Smartling\AuthApi\AuthTokenProvider::create($userIdentifier, $u
  * @param \Smartling\AuthApi\AuthApiInterface $authProvider
  * @param string $projectId
  * @param string $fileUri
- * @return bool
+ * @return array
  */
 function uploadContextDemo($authProvider, $projectId, $fileUri)
 {
@@ -58,7 +59,7 @@ function uploadContextDemo($authProvider, $projectId, $fileUri)
     $context = \Smartling\Context\ContextApi::create($authProvider, $projectId);
     $params = new UploadContextParameters();
     $params->setContextFileUri($fileUri);
-    $params->setName('test_context.html');
+    $params->setName('context.html');
     $st = microtime(true);
 
     try {
@@ -83,7 +84,7 @@ function uploadContextDemo($authProvider, $projectId, $fileUri)
  * @param \Smartling\AuthApi\AuthApiInterface $authProvider
  * @param string $projectId
  * @param $contextUid
- * @return bool
+ * @return array
  */
 function matchContextDemo($authProvider, $projectId, $contextUid)
 {
@@ -109,5 +110,131 @@ function matchContextDemo($authProvider, $projectId, $contextUid)
     return $response;
 }
 
+/**
+ * @param \Smartling\AuthApi\AuthApiInterface $authProvider
+ * @param string $projectId
+ * @param string $fileUri
+ * @return array
+ */
+function uploadAndMatchContextDemo($authProvider, $projectId, $fileUri)
+{
+    $response = FALSE;
+    $context = \Smartling\Context\ContextApi::create($authProvider, $projectId);
+    $params = new UploadContextParameters();
+    $params->setContextFileUri($fileUri);
+    $params->setName('context.html');
+    $st = microtime(true);
+
+    try {
+        $response = $context->uploadAndMatchContext($params);
+    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
+        var_dump($e->getErrors());
+    }
+
+    $et = microtime(TRUE);
+    $time = $et - $st;
+
+    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
+
+    if (!empty($response)) {
+        var_dump($response);
+    }
+
+    return $response;
+}
+
+/**
+ * @param \Smartling\AuthApi\AuthApiInterface $authProvider
+ * @param string $projectId
+ * @return array
+ */
+function getMissingResources($authProvider, $projectId)
+{
+    $response = FALSE;
+    $context = \Smartling\Context\ContextApi::create($authProvider, $projectId);
+    $st = microtime(true);
+
+    try {
+        $response = $context->getMissingResources();
+    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
+        var_dump($e->getErrors());
+    }
+
+    $et = microtime(TRUE);
+    $time = $et - $st;
+
+    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
+
+    if (!empty($response)) {
+        var_dump($response);
+    }
+
+    return $response;
+}
+
+/**
+ * @param \Smartling\AuthApi\AuthApiInterface $authProvider
+ * @param string $projectId
+ * @return bool
+ */
+function getAllMissingResourcesDemo($authProvider, $projectId) {
+    $response = FALSE;
+    $context = \Smartling\Context\ContextApi::create($authProvider, $projectId);
+    $st = microtime(true);
+
+    try {
+        $response = $context->getAllMissingResources();
+    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
+        var_dump($e->getErrors());
+    }
+
+    $et = microtime(TRUE);
+    $time = $et - $st;
+
+    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
+
+    if (!empty($response)) {
+        var_dump($response);
+    }
+
+    return $response;
+}
+
+/**
+ * @param \Smartling\AuthApi\AuthApiInterface $authProvider
+ * @param string $projectId
+ * @param string $resourceId
+ * @param string $fileUri
+ * @return bool
+ */
+function uploadResourceDemo($authProvider, $projectId, $resourceId, $fileUri) {
+    $response = FALSE;
+    $context = \Smartling\Context\ContextApi::create($authProvider, $projectId);
+    $st = microtime(true);
+
+    try {
+        $params = new UploadResourceParameters();
+        $params->setFile($fileUri);
+        $response = $context->uploadResource($resourceId, $params);
+    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
+        var_dump($e->getErrors());
+    }
+
+    $et = microtime(TRUE);
+    $time = $et - $st;
+
+    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
+
+    if (!empty($response)) {
+        var_dump($response);
+    }
+
+    return $response;
+}
+
 $contextInfo = uploadContextDemo($authProvider, $projectId, '../tests/resources/context.html');
 $response = matchContextDemo($authProvider, $projectId, $contextInfo['contextUid']);
+$response = uploadAndMatchContextDemo($authProvider, $projectId, '../tests/resources/context.html');
+$missingResources = getMissingResources($authProvider, $projectId);
+$allMissingResources = getAllMissingResourcesDemo($authProvider, $projectId);
+$uploadedResourceResponse = uploadResourceDemo($authProvider, $projectId, '[resource_id]', '../tests/resources/test.png');
diff --git a/api-sdk-php/examples/jobs-example.php b/api-sdk-php/examples/jobs-example.php
deleted file mode 100644
index aac24e5..0000000
--- a/api-sdk-php/examples/jobs-example.php
+++ /dev/null
@@ -1,335 +0,0 @@
-<?php
-
-error_reporting(E_ALL);
-
-/**
- * This file contains examples of Smartling API 2.x usage.
- *
- * How to use:
- * run "php example.php --project-id={PROJECT_ID} --user-id={USER_IDENTIFIER} --secret-key={SECRET_KEY}" in console
- *
- * Be sure you that dependencies are solved bu composer BEFORE running.
- */
-
-use Smartling\Jobs\Params\AddFileToJobParameters;
-
-$longOpts = [
-    'project-id:',
-    'user-id:',
-    'secret-key:',
-];
-
-$options = getopt('', $longOpts);
-
-if (
-    !array_key_exists('project-id', $options)
-    || !array_key_exists('user-id', $options)
-    || !array_key_exists('secret-key', $options)
-) {
-    echo 'Missing required params.' . PHP_EOL;
-    exit;
-}
-
-$autoloader = '../vendor/autoload.php';
-
-if (!file_exists($autoloader) || !is_readable($autoloader)) {
-    echo 'Error. Autoloader not found. Seems you didn\'t run:' . PHP_EOL . '    composer update' . PHP_EOL;
-    exit;
-}
-else {
-    /** @noinspection UntrustedInclusionInspection */
-    require_once '../vendor/autoload.php';
-}
-
-$projectId = $options['project-id'];
-$userIdentifier = $options['user-id'];
-$userSecretKey = $options['secret-key'];
-$authProvider = \Smartling\AuthApi\AuthTokenProvider::create($userIdentifier, $userSecretKey);
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @return bool
- */
-function listJobsDemo($authProvider, $projectId)
-{
-    $response = [];
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $st = microtime(true);
-
-    try {
-        $response = $jobs->listJobs(new \Smartling\Jobs\Params\ListJobsParameters());
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    if (!empty($response)) {
-        echo vsprintf('Total Jobs got: %s.%s', [$response['totalCount'], "\n\r"]);
-
-        foreach ($response['items'] as $item) {
-            echo vsprintf('Job "%s", UID(%s), dueDate is %s and has locales:%s.%s', [
-                $item['jobName'],
-                $item['translationJobUid'],
-                $item['dueDate'],
-                implode(',', $item['targetLocaleIds']),
-                "\n\r"
-            ]);
-        }
-    }
-
-    return $response;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @return string
- */
-function createJobDemo($authProvider, $projectId)
-{
-    $result = false;
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $params = new \Smartling\Jobs\Params\CreateJobParameters();
-    $params->setName("Test Job Name " . time());
-    $params->setDescription("Test Job Description " . time());
-    $params->setDueDate(DateTime::createFromFormat('Y-m-d H:i:s', '2020-01-01 19:19:17', new DateTimeZone('UTC')));
-    $params->setTargetLocales(['es', 'fr']);
-    $st = microtime(true);
-
-    try {
-        $response = $jobs->createJob($params);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    if (!empty($response)) {
-        echo vsprintf('Created Job "%s", UID(%s), dueDate is %s with locales:%s.%s', [
-            $response['jobName'],
-            $response['translationJobUid'],
-            $response['dueDate'],
-            implode(',', $response['targetLocaleIds']),
-            "\n\r"
-        ]);
-
-        $result = $response['translationJobUid'];
-    }
-
-    return $result;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @param string $jobId
- * @return string
- */
-function updateJobDemo($authProvider, $projectId, $jobId)
-{
-    $result = false;
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $params = new \Smartling\Jobs\Params\UpdateJobParameters();
-    $params->setName("Test Job Name Updated " . time());
-    $params->setDescription("Test Job Description Updated " . time());
-    $params->setDueDate(DateTime::createFromFormat('Y-m-d H:i:s', '2030-01-01 19:19:17', new DateTimeZone('UTC')));
-    $st = microtime(true);
-
-    try {
-        $response = $jobs->updateJob($jobId, $params);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    if (!empty($response)) {
-        echo vsprintf('Updated Job "%s", UID(%s), dueDate is %s with locales:%s.%s', [
-            $response['jobName'],
-            $response['translationJobUid'],
-            $response['dueDate'],
-            implode(',', $response['targetLocaleIds']),
-            "\n\r"
-        ]);
-
-        $result = $response['translationJobUid'];
-    }
-
-    return $result;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @param string $jobId
- * @return string
- */
-function cancelJobDemo($authProvider, $projectId, $jobId)
-{
-    $response = false;
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $params = new \Smartling\Jobs\Params\CancelJobParameters();
-    $params->setReason('Some reason to cancel');
-    $st = microtime(true);
-
-    try {
-        $response = $jobs->cancelJob($jobId, $params);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    return $response;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @param string $jobId
- * @return bool
- */
-function getJobDemo($authProvider, $projectId, $jobId)
-{
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $info = false;
-    $st = microtime(true);
-
-    try {
-        $info = $jobs->getJob($jobId);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    if (!empty($info)) {
-        echo vsprintf('Got job "%s", UID(%s), dueDate is %s with locales:%s.%s', [
-            $info['jobName'],
-            $info['translationJobUid'],
-            $info['dueDate'],
-            implode(',', $info['targetLocaleIds']),
-            "\n\r"
-        ]);
-    }
-
-    return $info;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @param string $fileUri
- * @return bool
- */
-function searchJobDemo($authProvider, $projectId, $fileUri)
-{
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $info = false;
-    $searchParameters = new \Smartling\Jobs\Params\SearchJobsParameters();
-    $searchParameters->setFileUris([
-        $fileUri,
-    ]);
-    $st = microtime(true);
-
-    try {
-        $info = $jobs->searchJobs($searchParameters);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    if (!empty($info)) {
-      echo vsprintf('Found jobs:%s', ["\n\r"]);
-
-      var_dump($info['items']);
-    }
-
-    return $info;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @param string $jobId
- * @param string $fileUri
- * @return mixed
- */
-function addFileToJobDemo($authProvider, $projectId, $jobId, $fileUri)
-{
-    $response = false;
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $params = new AddFileToJobParameters();
-    $params->setFileUri($fileUri);
-    $st = microtime(true);
-
-    try {
-        $response = $jobs->addFileToJob($jobId, $params);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    return $response;
-}
-
-/**
- * @param \Smartling\AuthApi\AuthApiInterface $authProvider
- * @param string $projectId
- * @param string $jobId
- * @return bool
- */
-function authorizeJobDemo($authProvider, $projectId, $jobId)
-{
-    $response = false;
-    $jobs = \Smartling\Jobs\JobsApi::create($authProvider, $projectId);
-    $st = microtime(true);
-
-    try {
-        $response = $jobs->authorizeJob($jobId);
-    } catch (\Smartling\Exceptions\SmartlingApiException $e) {
-        var_dump($e->getErrors());
-    }
-
-    $et = microtime(true);
-    $time = $et - $st;
-
-    echo vsprintf('Request took %s seconds.%s', [round($time, 3), "\n\r"]);
-
-    return $response;
-}
-
-$fileUri = 'JobID1_en_fr.xml';
-$jobs = listJobsDemo($authProvider, $projectId);
-$jobId = createJobDemo($authProvider, $projectId);
-$jobId = updateJobDemo($authProvider, $projectId, $jobId);
-$job = getJobDemo($authProvider, $projectId, $jobId);
-$isFileAdded = addFileToJobDemo($authProvider, $projectId, $jobId, $fileUri);
-$job = searchJobDemo($authProvider, $projectId, $fileUri);
-$isAuthorized = authorizeJobDemo($authProvider, $projectId, $jobId);
-$isCanceled = cancelJobDemo($authProvider, $projectId, $jobId);
diff --git a/api-sdk-php/src/BaseApiAbstract.php b/api-sdk-php/src/BaseApiAbstract.php
index f9e6f24..9c2dc69 100755
--- a/api-sdk-php/src/BaseApiAbstract.php
+++ b/api-sdk-php/src/BaseApiAbstract.php
@@ -283,11 +283,11 @@ abstract class BaseApiAbstract
     }
 
     /**
-     * @param array $requestData
+     * @param mixed $requestData
      *
      * @return array
      */
-    protected function processBodyOptions(array $requestData = [])
+    protected function processBodyOptions($requestData = [])
     {
         if (!empty($requestData['multipart'])) {
             $body = [];
@@ -406,9 +406,10 @@ abstract class BaseApiAbstract
      * @param array $options
      * @param $method
      * @param bool $returnRawResponseBody
-     * @return bool true on SUCCESS and empty data
-     *          string on $processResponseBody = false
-     * array otherwise
+     * @return  mixed.
+     *          true on SUCCESS and empty data
+     *          string on $returnRawResponseBody = true
+     *          array otherwise
      * @throws \Smartling\Exceptions\SmartlingApiException
      */
     protected function sendRequest($uri, array $options, $method, $returnRawResponseBody = false)
@@ -421,7 +422,10 @@ abstract class BaseApiAbstract
             $logRequestData['headers']['Authorization'] = substr($logRequestData['headers']['Authorization'], 0,
                     12) . '*****';
         }
-        if (isset($logRequestData['json']['userIdentifier'])) {
+        if (isset($logRequestData['json']) &&
+            is_array($logRequestData['json']) &&
+            isset($logRequestData['json']['userIdentifier'])
+        ) {
             $logRequestData['json']['userIdentifier'] = substr($logRequestData['json']['userIdentifier'], 0,
                     5) . '*****';
             $logRequestData['json']['userSecret'] = substr($logRequestData['json']['userSecret'], 0, 5) . '*****';
@@ -485,12 +489,15 @@ abstract class BaseApiAbstract
                 if (!array_key_exists('response', $json)
                     || !is_array($json['response'])
                     || empty($json['response']['code'])
-                    || $json['response']['code'] !== 'SUCCESS'
+                    || !in_array($json['response']['code'], [
+                        'SUCCESS',
+                        'ACCEPTED',
+                    ])
                 ) {
                     $this->processError($response);
                 }
 
-                return isset($json['response']['data']) ? $json['response']['data'] : true;
+                return !empty($json['response']['data']) ? $json['response']['data'] : true;
 
             } catch (RuntimeException $e) {
                 $this->processError($response);
diff --git a/api-sdk-php/src/Context/ContextApi.php b/api-sdk-php/src/Context/ContextApi.php
index 964970a..70a4e0b 100644
--- a/api-sdk-php/src/Context/ContextApi.php
+++ b/api-sdk-php/src/Context/ContextApi.php
@@ -5,7 +5,10 @@ namespace Smartling\Context;
 use Psr\Log\LoggerInterface;
 use Smartling\AuthApi\AuthApiInterface;
 use Smartling\BaseApiAbstract;
+use Smartling\Context\Params\MissingResourcesParameters;
 use Smartling\Context\Params\UploadContextParameters;
+use Smartling\Context\Params\UploadResourceParameters;
+use Smartling\Exceptions\SmartlingApiException;
 
 /**
  * Class ContextApi
@@ -18,6 +21,32 @@ class ContextApi extends BaseApiAbstract
     const ENDPOINT_URL = 'https://api.smartling.com/context-api/v2/projects';
 
     /**
+     * Timeout in seconds.
+     *
+     * @var int
+     */
+    private $timeOut = 15;
+
+    /**
+     * @return int
+     */
+    public function getTimeOut() {
+        return $this->timeOut;
+    }
+
+    /**
+     * @param int $timeOut
+     * @throws \InvalidArgumentException
+     */
+    public function setTimeOut($timeOut) {
+        if ($timeOut <= 0) {
+            throw new \InvalidArgumentException('Timeout value must be more or grater then zero.');
+        }
+
+        $this->timeOut = $timeOut;
+    }
+
+    /**
      * Instantiates Context API object.
      *
      * @param AuthApiInterface $authProvider
@@ -39,13 +68,13 @@ class ContextApi extends BaseApiAbstract
     /**
      * {@inheritdoc}
      */
-    protected function processBodyOptions(array $requestData = []) {
+    protected function processBodyOptions($requestData = []) {
         $opts = parent::processBodyOptions($requestData);
-        $key = 'content';
+        $keys = ['content', 'resource'];
 
         if (!empty($opts['multipart'])) {
             foreach ($opts['multipart'] as &$data) {
-                if ($data['name'] == $key) {
+                if (in_array($data['name'], $keys)) {
                     $data['contents'] = $this->readFile($data['contents']);
                 }
             }
@@ -55,11 +84,21 @@ class ContextApi extends BaseApiAbstract
     }
 
     /**
+     * {@inheritdoc}
+     */
+    protected function getDefaultRequestData($parametersType, $parameters, $auth = true, $httpErrors = false) {
+        $requestData = parent::getDefaultRequestData($parametersType, $parameters, $auth = true, $httpErrors = false);
+        $requestData['headers']['X-SL-Context-Source'] = $this->getXSLContextSourceHeader();
+
+        return $requestData;
+    }
+
+    /**
      * Returns X-SL-Context-Source header.
      *
      * @return string
      */
-    public function getXSLContextSourceHeader() {
+    private function getXSLContextSourceHeader() {
         return vsprintf('group=connectors;name=%s;version=%s', [
             static::getCurrentClientId(),
             static::getCurrentClientVersion(),
@@ -76,26 +115,111 @@ class ContextApi extends BaseApiAbstract
     public function uploadContext(UploadContextParameters $params)
     {
         $requestData = $this->getDefaultRequestData('multipart', $params->exportToArray());
-        $requestData['headers']['X-SL-Context-Source'] = $this->getXSLContextSourceHeader();
 
         return $this->sendRequest('contexts', $requestData, self::HTTP_METHOD_POST);
     }
 
-  /**
-   * Match context.
-   *
-   * @param $contextUid
-   * @return array
-   * @throws \Smartling\Exceptions\SmartlingApiException
-   */
+    /**
+     * Match context.
+     *
+     * @param $contextUid
+     * @return array
+     * @throws \Smartling\Exceptions\SmartlingApiException
+     */
     public function matchContext($contextUid)
     {
         $endpoint = vsprintf('contexts/%s/match/async', $contextUid);
         $requestData = $this->getDefaultRequestData('form_params', []);
         $requestData['headers']['Content-Type'] = 'application/json';
-        $requestData['headers']['X-SL-Context-Source'] = $this->getXSLContextSourceHeader();
 
         return $this->sendRequest($endpoint, $requestData, self::HTTP_METHOD_POST);
     }
 
+    /**
+     * Upload and match async.
+     *
+     * @param \Smartling\Context\Params\UploadContextParameters $params
+     * @return array
+     * @throws \Smartling\Exceptions\SmartlingApiException
+     */
+    public function uploadAndMatchContext(UploadContextParameters $params)
+    {
+        $requestData = $this->getDefaultRequestData('multipart', $params->exportToArray());
+
+        return $this->sendRequest('contexts/upload-and-match-async', $requestData, self::HTTP_METHOD_POST);
+    }
+
+    /**
+     * Get missing resources.
+     *
+     * @param MissingResourcesParameters|null $params
+     * @return array
+     * @throws \Smartling\Exceptions\SmartlingApiException
+     */
+    public function getMissingResources(MissingResourcesParameters $params = null) {
+        $requestData = $this->getDefaultRequestData('query', is_null($params) ? [] : $params->exportToArray());
+
+        return $this->sendRequest('missing-resources', $requestData, self::HTTP_METHOD_GET);
+    }
+
+    /**
+     * Get all missing resources.
+     *
+     * @return array
+     * Contains next keys:
+     *  - "items": array of missing resources
+     *  - "all": boolean which indicates whether function has read all the
+     *           available items or not.
+     *
+     * @throws SmartlingApiException
+     */
+    public function getAllMissingResources() {
+        $missingResources = [];
+        $offset = FALSE;
+        $all = TRUE;
+        $start_time = time();
+
+        while (!is_null($offset)) {
+            $delta = time() - $start_time;
+
+            if ($delta > $this->getTimeOut()) {
+                $all = FALSE;
+                break;
+            }
+
+            if (!$offset) {
+                $params = NULL;
+            }
+            else {
+                $params = new MissingResourcesParameters();
+                $params->setOffset($offset);
+            }
+
+            $response = $this->getMissingResources($params);
+            $offset = !empty($response['offset']) ? $response['offset'] : NULL;
+            $missingResources = array_merge($missingResources, $response['items']);
+        }
+
+        return [
+            'items' => $missingResources,
+            'all' => $all,
+        ];
+    }
+
+    /**
+     * Upload resource.
+     *
+     * @param $resourceId
+     * @param \Smartling\Context\Params\UploadResourceParameters $params
+     * @return bool
+     * @throws SmartlingApiException
+     */
+    public function uploadResource($resourceId, UploadResourceParameters $params)
+    {
+        $endpoint = vsprintf('resources/%s', $resourceId);
+        $requestData = $this->getDefaultRequestData('multipart', $params->exportToArray());
+
+        return $this->sendRequest($endpoint, $requestData, self::HTTP_METHOD_PUT);
+    }
+
 }
diff --git a/api-sdk-php/src/Context/Params/MissingResourcesParameters.php b/api-sdk-php/src/Context/Params/MissingResourcesParameters.php
new file mode 100644
index 0000000..1bb13a4
--- /dev/null
+++ b/api-sdk-php/src/Context/Params/MissingResourcesParameters.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace Smartling\Context\Params;
+
+use Smartling\Parameters\BaseParameters;
+
+/**
+ * Class MissingResourcesParameters
+ * @package Context\Params
+ */
+class MissingResourcesParameters extends BaseParameters
+{
+
+    public function setOffset($offset)
+    {
+        $this->params['offset'] = $offset;
+    }
+
+}
diff --git a/api-sdk-php/src/Context/Params/UploadResourceParameters.php b/api-sdk-php/src/Context/Params/UploadResourceParameters.php
new file mode 100644
index 0000000..ecbc3cf
--- /dev/null
+++ b/api-sdk-php/src/Context/Params/UploadResourceParameters.php
@@ -0,0 +1,18 @@
+<?php
+
+namespace Smartling\Context\Params;
+
+use Smartling\Parameters\BaseParameters;
+
+/**
+ * Class UploadResourceParameters
+ * @package Context\Params
+ */
+class UploadResourceParameters extends BaseParameters
+{
+
+    public function setFile($resource) {
+        $this->params['resource'] = $resource;
+    }
+
+}
diff --git a/api-sdk-php/src/Exceptions/SmartlingApiException.php b/api-sdk-php/src/Exceptions/SmartlingApiException.php
index fcdbb82..865298f 100755
--- a/api-sdk-php/src/Exceptions/SmartlingApiException.php
+++ b/api-sdk-php/src/Exceptions/SmartlingApiException.php
@@ -41,6 +41,7 @@ class SmartlingApiException extends \Exception
         if (is_string($errors)) {
             $message = $errors;
         } elseif (is_array($errors)) {
+            $message = print_r($errors, TRUE);
             $this->errors = $errors;
         }
         
diff --git a/api-sdk-php/src/File/FileApi.php b/api-sdk-php/src/File/FileApi.php
index 01687ab..9f1b5c0 100755
--- a/api-sdk-php/src/File/FileApi.php
+++ b/api-sdk-php/src/File/FileApi.php
@@ -43,7 +43,7 @@ class FileApi extends BaseApiAbstract
     /**
      * {@inheritdoc}
      */
-    protected function processBodyOptions(array $requestData = []) {
+    protected function processBodyOptions($requestData = []) {
         $opts = parent::processBodyOptions($requestData);
         $key = 'file';
 
diff --git a/api-sdk-php/src/Jobs/JobStatus.php b/api-sdk-php/src/Jobs/JobStatus.php
deleted file mode 100644
index 21ab410..0000000
--- a/api-sdk-php/src/Jobs/JobStatus.php
+++ /dev/null
@@ -1,14 +0,0 @@
-<?php
-
-namespace Smartling\Jobs;
-
-
-class JobStatus
-{
-    // const DRAFT                     = 'DRAFT';
-    const AWAITING_AUTHORIZATION    = 'AWAITING_AUTHORIZATION';
-    const IN_PROGRESS               = 'IN_PROGRESS';
-    const COMPLETED                 = 'COMPLETED';
-    // const REJECTED                  = 'REJECTED';
-    const CANCELLED                 = 'CANCELLED';
-}
\ No newline at end of file
diff --git a/api-sdk-php/src/Jobs/JobsApi.php b/api-sdk-php/src/Jobs/JobsApi.php
deleted file mode 100644
index 4d7fd74..0000000
--- a/api-sdk-php/src/Jobs/JobsApi.php
+++ /dev/null
@@ -1,160 +0,0 @@
-<?php
-
-namespace Smartling\Jobs;
-
-use Psr\Log\LoggerInterface;
-use Smartling\AuthApi\AuthApiInterface;
-use Smartling\BaseApiAbstract;
-use Smartling\Jobs\Params\AddFileToJobParameters;
-use Smartling\Jobs\Params\CancelJobParameters;
-use Smartling\Jobs\Params\CreateJobParameters;
-use Smartling\Jobs\Params\ListJobsParameters;
-use Smartling\Jobs\Params\SearchJobsParameters;
-use Smartling\Jobs\Params\UpdateJobParameters;
-
-/**
- * Class JobsApi
- *
- * @package Smartling\Project
- */
-class JobsApi extends BaseApiAbstract
-{
-
-    const ENDPOINT_URL = 'https://api.smartling.com/jobs-api/v2/projects';
-
-    /**
-     * Instantiates Jobs API object.
-     *
-     * @param AuthApiInterface $authProvider
-     * @param string $projectId
-     * @param LoggerInterface $logger
-     *
-     * @return JobsApi
-     */
-    public static function create(AuthApiInterface $authProvider, $projectId, $logger = null)
-    {
-
-        $client = self::initializeHttpClient(self::ENDPOINT_URL);
-
-        $instance = new self($projectId, $client, $logger, self::ENDPOINT_URL);
-        $instance->setAuth($authProvider);
-
-        return $instance;
-    }
-
-    /**
-     * Creates a job.
-     *
-     * @param CreateJobParameters $parameters
-     * @return array
-     */
-    public function createJob(CreateJobParameters $parameters)
-    {
-        $requestData = $this->getDefaultRequestData('json', $parameters->exportToArray());
-
-        return $this->sendRequest('jobs', $requestData, self::HTTP_METHOD_POST);
-    }
-
-    /**
-    * Updates a job.
-    *
-    * @param string $jobId
-    * @param UpdateJobParameters $parameters
-    * @return array
-    */
-    public function updateJob($jobId, UpdateJobParameters $parameters)
-    {
-        $requestData = $this->getDefaultRequestData('json', $parameters->exportToArray());
-
-        return $this->sendRequest('jobs/' . $jobId, $requestData, self::HTTP_METHOD_PUT);
-    }
-
-    /**
-     * Cancels a job.
-     *
-     * @param string $jobId
-     * @param CancelJobParameters $parameters
-     * @return bool
-     */
-    public function cancelJob($jobId, CancelJobParameters $parameters)
-    {
-        $endpoint = vsprintf('jobs/%s/cancel', [$jobId]);
-        $requestData = $this->getDefaultRequestData('json', $parameters->exportToArray());
-
-        return $this->sendRequest($endpoint, $requestData, self::HTTP_METHOD_POST);
-    }
-
-    /**
-     * Returns a list of jobs.
-     *
-     * @param ListJobsParameters $parameters
-     * @return array
-     */
-    public function listJobs(ListJobsParameters $parameters)
-    {
-        $requestData = $this->getDefaultRequestData('query', $parameters->exportToArray());
-
-        return $this->sendRequest('jobs', $requestData, self::HTTP_METHOD_GET);
-    }
-
-    /**
-     * Returns a job.
-     *
-     * @param string $jobId
-     * @return array
-     */
-    public function getJob($jobId)
-    {
-        $requestData = $this->getDefaultRequestData('query', []);
-
-        return $this->sendRequest('jobs/' . $jobId, $requestData, self::HTTP_METHOD_GET);
-    }
-
-    /**
-     * Authorizes a job.
-     *
-     * @param $jobId
-     * @return bool
-     * @throws \Smartling\Exceptions\SmartlingApiException
-     */
-    public function authorizeJob($jobId)
-    {
-        $endpoint = vsprintf('jobs/%s/authorize', [$jobId]);
-        $requestData = $this->getDefaultRequestData('form_params', []);
-        $requestData['headers']['Content-Type'] = 'application/json';
-
-        return $this->sendRequest($endpoint, $requestData, self::HTTP_METHOD_POST);
-    }
-
-    /**
-     * Adds file to a job.
-     *
-     * @param $jobId
-     * @param \Smartling\Jobs\Params\AddFileToJobParameters $parameters
-     * @return array
-     * @throws \Smartling\Exceptions\SmartlingApiException
-     */
-    public function addFileToJob($jobId, AddFileToJobParameters $parameters)
-    {
-        $endpoint = vsprintf('jobs/%s/file/add', [$jobId]);
-        $requestData = $this->getDefaultRequestData('json', $parameters->exportToArray());
-
-        return $this->sendRequest($endpoint, $requestData, self::HTTP_METHOD_POST);
-    }
-
-    /**
-     * Search/Find Job(s), based on different query criteria passed in.
-     *
-     * @param \Smartling\Jobs\Params\SearchJobsParameters $parameters
-     *
-     * @return array
-     * @throws \Smartling\Exceptions\SmartlingApiException
-     */
-    public function searchJobs(SearchJobsParameters $parameters)
-    {
-        $requestData = $this->getDefaultRequestData('json', $parameters->exportToArray());
-
-        return $this->sendRequest('jobs/search', $requestData, self::HTTP_METHOD_POST);
-    }
-
-}
diff --git a/api-sdk-php/src/Jobs/Params/AddFileToJobParameters.php b/api-sdk-php/src/Jobs/Params/AddFileToJobParameters.php
deleted file mode 100644
index c32dcb4..0000000
--- a/api-sdk-php/src/Jobs/Params/AddFileToJobParameters.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-namespace Smartling\Jobs\Params;
-
-use Smartling\Parameters\BaseParameters;
-
-/**
- * Class AddFileToJobParameters
- * @package Jobs\Params
- */
-class AddFileToJobParameters extends BaseParameters
-{
-
-    /**
-     * @param string $fileUri
-     */
-    public function setFileUri($fileUri) {
-        $this->params['fileUri'] = $fileUri;
-    }
-
-}
diff --git a/api-sdk-php/src/Jobs/Params/CancelJobParameters.php b/api-sdk-php/src/Jobs/Params/CancelJobParameters.php
deleted file mode 100644
index db7b420..0000000
--- a/api-sdk-php/src/Jobs/Params/CancelJobParameters.php
+++ /dev/null
@@ -1,21 +0,0 @@
-<?php
-
-namespace Smartling\Jobs\Params;
-
-use Smartling\Parameters\BaseParameters;
-
-/**
- * Class CancelJobParameters
- * @package Jobs\Params
- */
-class CancelJobParameters extends BaseParameters
-{
-
-  /**
-   * @param string $reason
-   */
-  public function setReason($reason) {
-      $this->params['reason'] = $reason;
-  }
-
-}
diff --git a/api-sdk-php/src/Jobs/Params/CreateJobParameters.php b/api-sdk-php/src/Jobs/Params/CreateJobParameters.php
deleted file mode 100644
index 1527973..0000000
--- a/api-sdk-php/src/Jobs/Params/CreateJobParameters.php
+++ /dev/null
@@ -1,19 +0,0 @@
-<?php
-
-namespace Smartling\Jobs\Params;
-
-/**
- * Class CreateJobParameters
- * @package Jobs\Params
- */
-class CreateJobParameters extends UpdateJobParameters
-{
-
-  /**
-   * @param array $targetLocales
-   */
-  public function setTargetLocales(array $targetLocales = []) {
-      $this->params['targetLocaleIds'] = $targetLocales;
-  }
-
-}
diff --git a/api-sdk-php/src/Jobs/Params/ListJobsParameters.php b/api-sdk-php/src/Jobs/Params/ListJobsParameters.php
deleted file mode 100644
index dee3c3a..0000000
--- a/api-sdk-php/src/Jobs/Params/ListJobsParameters.php
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-
-namespace Smartling\Jobs\Params;
-
-use Smartling\Parameters\BaseParameters;
-
-class ListJobsParameters extends BaseParameters
-{
-
-    public function __construct($jobName = null, $limit = null, $offset = null)
-    {
-        $this->setName($jobName);
-        $this->setLimit($limit);
-        $this->setOffset($offset);
-    }
-
-    public function setName($jobName)
-    {
-        if (null !== $jobName) {
-            if (mb_strlen($jobName, 'UTF-8') >= 170) {
-                throw new \InvalidArgumentException('Job name should be less than 170 characters.');
-            }
-            $this->params['jobName'] = $jobName;
-        }
-    }
-
-    public function setLimit($limit)
-    {
-        if (null !== $limit && 0 < (int)$limit) {
-            $this->params['limit'] = (int)$limit;
-        }
-    }
-
-    public function setOffset($offset)
-    {
-        if (null !== $offset && 0 < (int)$offset) {
-            $this->params['offset'] = (int)$offset;
-        }
-
-    }
-}
\ No newline at end of file
diff --git a/api-sdk-php/src/Jobs/Params/SearchJobsParameters.php b/api-sdk-php/src/Jobs/Params/SearchJobsParameters.php
deleted file mode 100644
index 717bf90..0000000
--- a/api-sdk-php/src/Jobs/Params/SearchJobsParameters.php
+++ /dev/null
@@ -1,33 +0,0 @@
-<?php
-
-namespace Smartling\Jobs\Params;
-
-use Smartling\Parameters\BaseParameters;
-
-/**
- * Class SearchJobsParameters
- *
- * @package Smartling\Params
- */
-class SearchJobsParameters extends BaseParameters
-{
-
-  /**
-   * Sets hash codes for searching.
-   *
-   * @param array $hashCodes
-   */
-  public function setHashCodes(array $hashCodes) {
-    $this->params['hashcodes'] = $hashCodes;
-  }
-
-  /**
-   * Sets file uris for searching.
-   *
-   * @param array $fileUris
-   */
-  public function setFileUris(array $fileUris) {
-    $this->params['fileUris'] = $fileUris;
-  }
-
-}
diff --git a/api-sdk-php/src/Jobs/Params/UpdateJobParameters.php b/api-sdk-php/src/Jobs/Params/UpdateJobParameters.php
deleted file mode 100644
index 640fe5b..0000000
--- a/api-sdk-php/src/Jobs/Params/UpdateJobParameters.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-namespace Smartling\Jobs\Params;
-
-use Smartling\Parameters\BaseParameters;
-
-/**
- * Class UpdateJobParameters
- * @package Jobs\Params
- */
-class UpdateJobParameters extends BaseParameters
-{
-
-    public function setName($jobName)
-    {
-        if (mb_strlen($jobName, 'UTF-8') >= 170) {
-            throw new \InvalidArgumentException('Job name should be less than 170 characters.');
-        }
-        $this->params['jobName'] = $jobName;
-    }
-
-    public function setDescription($description)
-    {
-        if (mb_strlen($description, 'UTF-8') >= 2000) {
-            throw new \InvalidArgumentException('Job description should be less than 2000 characters.');
-        }
-        $this->params['description'] = $description;
-    }
-
-    public function setDueDate(\DateTime $dueDate)
-    {
-        if ($dueDate->getTimestamp() < time()) {
-            throw new \InvalidArgumentException('Job Due Date cannot be in the past.');
-        }
-        $this->params['dueDate'] = $dueDate->format('Y-m-d\TH:i:s\Z');
-    }
-
-}
diff --git a/api-sdk-php/src/Parameters/BaseParameters.php b/api-sdk-php/src/Parameters/BaseParameters.php
old mode 100644
new mode 100755
diff --git a/api-sdk-php/src/Parameters/ParameterInterface.php b/api-sdk-php/src/Parameters/ParameterInterface.php
old mode 100644
new mode 100755
diff --git a/api-sdk-php/tests/functional/ContextApiFunctionalTest.php b/api-sdk-php/tests/functional/ContextApiFunctionalTest.php
old mode 100644
new mode 100755
index 6018351..4e301de
--- a/api-sdk-php/tests/functional/ContextApiFunctionalTest.php
+++ b/api-sdk-php/tests/functional/ContextApiFunctionalTest.php
@@ -5,6 +5,7 @@ namespace Smartling\Tests\Functional;
 use PHPUnit_Framework_TestCase;
 use Smartling\AuthApi\AuthTokenProvider;
 use Smartling\Context\Params\UploadContextParameters;
+use Smartling\Context\Params\UploadResourceParameters;
 use Smartling\Exceptions\SmartlingApiException;
 use Smartling\Context\ContextApi;
 
@@ -75,4 +76,47 @@ class ContextApiFunctionalTest extends PHPUnit_Framework_TestCase
         }
     }
 
+    /**
+     * Test for upload and match context.
+     */
+    public function testUploadAndMatchContext() {
+        try {
+            $params = new UploadContextParameters();
+            $params->setContextFileUri('tests/resources/context.html');
+            $params->setName('test_context.html');
+            $result = $this->contextApi->uploadAndMatchContext($params);
+
+            $this->assertArrayHasKey('matchId', $result);
+        } catch (SmartlingApiException $e) {
+            $this->fail($e->getMessage());
+        }
+    }
+
+    /**
+     * Test for get missing resources.
+     */
+    public function testGetMissingResources() {
+        try {
+            $result = $this->contextApi->getMissingResources();
+
+            $this->assertArrayHasKey('items', $result);
+        } catch (SmartlingApiException $e) {
+            $this->fail($e->getMessage());
+        }
+    }
+
+    /**
+     * Test for get all missing resources.
+     */
+    public function testGetAllMissingResources() {
+        try {
+            $result = $this->contextApi->getAllMissingResources();
+
+            $this->assertArrayHasKey('items', $result);
+            $this->assertArrayHasKey('all', $result);
+        } catch (SmartlingApiException $e) {
+            $this->fail($e->getMessage());
+        }
+    }
+
 }
diff --git a/api-sdk-php/tests/functional/FileApiFunctionalTest.php b/api-sdk-php/tests/functional/FileApiFunctionalTest.php
old mode 100644
new mode 100755
diff --git a/api-sdk-php/tests/functional/JobsApiFunctionalTest.php b/api-sdk-php/tests/functional/JobsApiFunctionalTest.php
deleted file mode 100644
index ee7024a..0000000
--- a/api-sdk-php/tests/functional/JobsApiFunctionalTest.php
+++ /dev/null
@@ -1,252 +0,0 @@
-<?php
-
-namespace Smartling\Tests\Functional;
-
-use DateTime;
-use DateTimeZone;
-use PHPUnit_Framework_TestCase;
-use Smartling\AuthApi\AuthTokenProvider;
-use Smartling\Exceptions\SmartlingApiException;
-use Smartling\File\FileApi;
-use Smartling\Jobs\JobsApi;
-use Smartling\Jobs\Params\AddFileToJobParameters;
-use Smartling\Jobs\Params\CancelJobParameters;
-use Smartling\Jobs\Params\CreateJobParameters;
-use Smartling\Jobs\Params\ListJobsParameters;
-use Smartling\Jobs\Params\SearchJobsParameters;
-use Smartling\Jobs\Params\UpdateJobParameters;
-
-/**
- * Test class for Jobs API examples.
- */
-class JobsApiFunctionalTest extends PHPUnit_Framework_TestCase
-{
-
-    /**
-     * @var JobsApi
-     */
-    private $jobsApi;
-
-    /**
-     * @var FileApi
-     */
-    private $fileApi;
-
-    /**
-     * @var string $jobId
-     */
-    private $jobId = FALSE;
-
-    /**
-     * Test mixture.
-     */
-    public function setUp() {
-        $projectId = getenv('project_id');
-        $userIdentifier = getenv('user_id');
-        $userSecretKey = getenv('user_key');
-
-        if (
-            empty($projectId) ||
-            empty($userIdentifier) ||
-            empty($userSecretKey)
-        ) {
-            $this->fail('Missing required parameters');
-        }
-
-        $authProvider = AuthTokenProvider::create($userIdentifier, $userSecretKey);
-        $this->jobsApi = JobsApi::create($authProvider, $projectId);
-        $this->fileApi = FileApi::create($authProvider, $projectId);
-
-        try {
-            $this->jobId = $this->createJob();
-        }
-        catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    public function tearDown() {
-        try {
-            $this->cancelJob($this->jobId);
-        }
-        catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    /**
-     * Create job.
-     *
-     * @return string
-     */
-    private function createJob() {
-        try {
-            $params = new CreateJobParameters();
-            $params->setName('Test Job Name ' . time());
-            $params->setDescription('Test Job Description ' . time());
-            $params->setDueDate(DateTime::createFromFormat('Y-m-d H:i:s', '2020-01-01 19:19:17', new DateTimeZone('UTC')));
-            $params->setTargetLocales(['es', 'fr']);
-            $result = $this->jobsApi->createJob($params);
-
-            $this->assertArrayHasKey('translationJobUid', $result);
-            $this->assertArrayHasKey('jobName', $result);
-            $this->assertArrayHasKey('targetLocaleIds', $result);
-            $this->assertArrayHasKey('description', $result);
-            $this->assertArrayHasKey('dueDate', $result);
-            $this->assertArrayHasKey('referenceNumber', $result);
-            $this->assertArrayHasKey('callbackUrl', $result);
-            $this->assertArrayHasKey('callbackMethod', $result);
-            $this->assertArrayHasKey('createdDate', $result);
-            $this->assertArrayHasKey('modifiedDate', $result);
-            $this->assertArrayHasKey('createdByUserUid', $result);
-            $this->assertArrayHasKey('modifiedByUserUid', $result);
-            $this->assertArrayHasKey('archived', $result);
-            $this->assertArrayHasKey('firstCompletedDate', $result);
-            $this->assertArrayHasKey('lastCompletedDate', $result);
-            $this->assertArrayHasKey('jobStatus', $result);
-
-            $result = $result['translationJobUid'];
-        } catch (SmartlingApiException $e) {
-            $result = FALSE;
-        }
-
-        return $result;
-    }
-
-    /**
-     * Cancel job.
-     *
-     * @param string $jobId
-     * @return bool
-     */
-    private function cancelJob($jobId) {
-        $params = new CancelJobParameters();
-        $params->setReason('Some reason to cancel');
-        return $this->jobsApi->cancelJob($jobId, $params);
-    }
-
-    /**
-     * Test for job list.
-     */
-    public function testJobsApiListJobs() {
-        try {
-            $result = $this->jobsApi->listJobs(new ListJobsParameters());
-
-            $this->assertArrayHasKey('totalCount', $result);
-            $this->assertArrayHasKey('items', $result);
-        } catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    /**
-     * Test for job update.
-     */
-    public function testJobsApiUpdateJob() {
-        try {
-            $params = new UpdateJobParameters();
-            $params->setName("Test Job Name Updated " . time());
-            $params->setDescription("Test Job Description Updated " . time());
-            $params->setDueDate(DateTime::createFromFormat('Y-m-d H:i:s', '2030-01-01 19:19:17', new DateTimeZone('UTC')));
-            $result = $this->jobsApi->updateJob($this->jobId, $params);
-
-            $this->assertArrayHasKey('translationJobUid', $result);
-            $this->assertArrayHasKey('jobName', $result);
-            $this->assertArrayHasKey('targetLocaleIds', $result);
-            $this->assertArrayHasKey('description', $result);
-            $this->assertArrayHasKey('dueDate', $result);
-            $this->assertArrayHasKey('referenceNumber', $result);
-            $this->assertArrayHasKey('callbackUrl', $result);
-            $this->assertArrayHasKey('callbackMethod', $result);
-            $this->assertArrayHasKey('createdDate', $result);
-            $this->assertArrayHasKey('modifiedDate', $result);
-            $this->assertArrayHasKey('createdByUserUid', $result);
-            $this->assertArrayHasKey('modifiedByUserUid', $result);
-            $this->assertArrayHasKey('archived', $result);
-            $this->assertArrayHasKey('firstCompletedDate', $result);
-            $this->assertArrayHasKey('lastCompletedDate', $result);
-            $this->assertArrayHasKey('jobStatus', $result);
-        } catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    /**
-     * Test for job get.
-     */
-    public function testJobsApiGetJob() {
-        try {
-            $result = $this->jobsApi->getJob($this->jobId);
-
-            $this->assertArrayHasKey('translationJobUid', $result);
-            $this->assertArrayHasKey('jobName', $result);
-            $this->assertArrayHasKey('targetLocaleIds', $result);
-            $this->assertArrayHasKey('description', $result);
-            $this->assertArrayHasKey('dueDate', $result);
-            $this->assertArrayHasKey('referenceNumber', $result);
-            $this->assertArrayHasKey('callbackUrl', $result);
-            $this->assertArrayHasKey('callbackMethod', $result);
-            $this->assertArrayHasKey('createdDate', $result);
-            $this->assertArrayHasKey('modifiedDate', $result);
-            $this->assertArrayHasKey('createdByUserUid', $result);
-            $this->assertArrayHasKey('modifiedByUserUid', $result);
-            $this->assertArrayHasKey('archived', $result);
-            $this->assertArrayHasKey('firstCompletedDate', $result);
-            $this->assertArrayHasKey('lastCompletedDate', $result);
-            $this->assertArrayHasKey('jobStatus', $result);
-            $this->assertArrayHasKey('issuesDetails', $result);
-            $this->assertArrayHasKey('sourceFiles', $result);
-        } catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    /**
-     * Test for add file to job get.
-     */
-    public function testJobsApiAddFileToJob() {
-        try {
-            $this->fileApi->uploadFile('tests/resources/test.xml', 'test.xml', 'xml');
-            $params = new AddFileToJobParameters();
-            $params->setFileUri('test.xml');
-            $result = $this->jobsApi->addFileToJob($this->jobId, $params);
-
-            $this->assertArrayHasKey('failCount', $result);
-            $this->assertArrayHasKey('successCount', $result);
-        } catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    /**
-     * Test for jobs search.
-     */
-    public function testJobsApiSearchJob() {
-        try {
-            $searchParameters = new SearchJobsParameters();
-            $searchParameters->setFileUris([
-                'some_file_to_search.xml',
-            ]);
-            $result = $this->jobsApi->searchJobs($searchParameters);
-
-            $this->assertArrayHasKey('totalCount', $result);
-            $this->assertArrayHasKey('items', $result);
-        } catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-    /**
-     * Test for job authorize.
-     */
-    public function testJobsApiAuthorizeJob() {
-        try {
-            $result = $this->jobsApi->authorizeJob($this->jobId);
-
-            $this->assertTrue($result);
-        } catch (SmartlingApiException $e) {
-            $this->fail($e->getMessage());
-        }
-    }
-
-}
diff --git a/api-sdk-php/tests/functional/ProjectApiFunctionalTest.php b/api-sdk-php/tests/functional/ProjectApiFunctionalTest.php
old mode 100644
new mode 100755
diff --git a/api-sdk-php/tests/resources/test.png b/api-sdk-php/tests/resources/test.png
new file mode 100644
index 0000000..c535af7
Binary files /dev/null and b/api-sdk-php/tests/resources/test.png differ
diff --git a/api-sdk-php/tests/unit/ApiTestAbstract.php b/api-sdk-php/tests/unit/ApiTestAbstract.php
index 3962da1..1993810 100644
--- a/api-sdk-php/tests/unit/ApiTestAbstract.php
+++ b/api-sdk-php/tests/unit/ApiTestAbstract.php
@@ -47,6 +47,11 @@ abstract class ApiTestAbstract extends \PHPUnit_Framework_TestCase
     protected $responseWithException = '{"response":{"data":null,"code":"VALIDATION_ERROR","errors":[{"message":"Validation error text"}]}}';
 
     /**
+     * @var string
+     */
+    protected $responseAsync = '{"response":{"data":{"message":"message", "url":"url"},"code":"ACCEPTED"}}';
+
+    /**
      * @var PHPUnit_Framework_MockObject_MockObject|ClientInterface
      */
     protected $client;
diff --git a/api-sdk-php/tests/unit/ContextApiTest.php b/api-sdk-php/tests/unit/ContextApiTest.php
index a2f4844..0dba103 100644
--- a/api-sdk-php/tests/unit/ContextApiTest.php
+++ b/api-sdk-php/tests/unit/ContextApiTest.php
@@ -3,8 +3,10 @@
 namespace Smartling\Tests;
 
 use Smartling\Context\ContextApi;
+use Smartling\Context\Params\MissingResourcesParameters;
 use Smartling\Context\Params\UploadContextParameters;
 use Smartling\Tests\Unit\ApiTestAbstract;
+use Smartling\Context\Params\UploadResourceParameters;
 
 
 /**
@@ -70,7 +72,7 @@ class ContextApiTest extends ApiTestAbstract
                         $this->authProvider->getTokenType(),
                         $this->authProvider->getAccessToken(),
                     ]),
-                    'X-SL-Context-Source' => $this->object->getXSLContextSourceHeader(),
+                    'X-SL-Context-Source' => $this->invokeMethod($this->object, 'getXSLContextSourceHeader'),
                 ],
                 'exceptions' => FALSE,
                 'multipart' => [
@@ -111,7 +113,7 @@ class ContextApiTest extends ApiTestAbstract
                         $this->authProvider->getAccessToken(),
                     ]),
                     'Content-Type' => 'application/json',
-                    'X-SL-Context-Source' => $this->object->getXSLContextSourceHeader(),
+                    'X-SL-Context-Source' => $this->invokeMethod($this->object, 'getXSLContextSourceHeader'),
               ],
               'exceptions' => FALSE,
               'form_params' => [],
@@ -121,4 +123,112 @@ class ContextApiTest extends ApiTestAbstract
         $this->object->matchContext($contextUid);
     }
 
+    /**
+     * @covers \Smartling\Context\ContextApi::uploadAndMatchContext
+     */
+    public function testUploadAndMatchContext() {
+        $params = new UploadContextParameters();
+        $params->setContextFileUri('./tests/resources/context.html');
+        $endpointUrl = vsprintf('%s/%s/contexts/upload-and-match-async', [
+            ContextApi::ENDPOINT_URL,
+            $this->projectId
+        ]);
+
+        $this->client
+            ->expects(self::once())
+            ->method('request')
+            ->with('post', $endpointUrl, [
+                'headers' => [
+                    'Accept' => 'application/json',
+                    'Authorization' => vsprintf('%s %s', [
+                        $this->authProvider->getTokenType(),
+                        $this->authProvider->getAccessToken(),
+                    ]),
+                    'X-SL-Context-Source' => $this->invokeMethod($this->object, 'getXSLContextSourceHeader'),
+                ],
+                'exceptions' => FALSE,
+                'multipart' => [
+                    [
+                        'name' => 'content',
+                        'contents' => $this->streamPlaceholder,
+                    ],
+                ],
+            ])
+            ->willReturn($this->responseMock);
+
+        $this->object->uploadAndMatchContext($params);
+    }
+
+    /**
+     * @covers \Smartling\Context\ContextApi::getMissingResources
+     */
+    public function testGetMissingResources() {
+        $offset = 'some_offset';
+        $params = new MissingResourcesParameters();
+        $params->setOffset($offset);
+        $endpointUrl = vsprintf('%s/%s/missing-resources', [
+            ContextApi::ENDPOINT_URL,
+            $this->projectId
+        ]);
+
+        $this->client
+            ->expects(self::once())
+            ->method('request')
+            ->with('get', $endpointUrl, [
+                'headers' => [
+                    'Accept' => 'application/json',
+                    'Authorization' => vsprintf('%s %s', [
+                        $this->authProvider->getTokenType(),
+                        $this->authProvider->getAccessToken(),
+                    ]),
+                    'X-SL-Context-Source' => $this->invokeMethod($this->object, 'getXSLContextSourceHeader'),
+                ],
+                'exceptions' => FALSE,
+                'query' => [
+                    'offset' => $offset,
+                ],
+            ])
+            ->willReturn($this->responseMock);
+
+        $this->object->getMissingResources($params);
+    }
+
+    /**
+     * @covers \Smartling\Context\ContextApi::uploadResource
+     */
+    public function testUploadResource() {
+        $resourceId = 'some_resource_id';
+        $params = new UploadResourceParameters();
+        $params->setFile('./tests/resources/test.png');
+        $endpointUrl = vsprintf('%s/%s/resources/%s', [
+            ContextApi::ENDPOINT_URL,
+            $this->projectId,
+            $resourceId,
+        ]);
+
+        $this->client
+            ->expects(self::once())
+            ->method('request')
+            ->with('put', $endpointUrl, [
+                'headers' => [
+                    'Accept' => 'application/json',
+                    'Authorization' => vsprintf('%s %s', [
+                        $this->authProvider->getTokenType(),
+                        $this->authProvider->getAccessToken(),
+                    ]),
+                    'X-SL-Context-Source' => $this->invokeMethod($this->object, 'getXSLContextSourceHeader'),
+                ],
+                'exceptions' => FALSE,
+                'multipart' => [
+                    [
+                        'name' => 'resource',
+                        'contents' => $this->streamPlaceholder,
+                    ],
+                ],
+            ])
+            ->willReturn($this->responseMock);
+
+        $this->object->uploadResource($resourceId, $params);
+    }
+
 }
diff --git a/api-sdk-php/tests/unit/ExceptionTest.php b/api-sdk-php/tests/unit/ExceptionTest.php
new file mode 100644
index 0000000..95b7831
--- /dev/null
+++ b/api-sdk-php/tests/unit/ExceptionTest.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace Smartling\Tests;
+use Smartling\Exceptions\SmartlingApiException;
+
+/**
+ * Test class for Smartling\Exceptions\SmartlingApiException.
+ */
+class ExceptionTest extends \PHPUnit_Framework_TestCase
+{
+
+    /**
+     * Check exception's constructor with string error passed in.
+     */
+    public function testConstructorStringMessage() {
+        $exceptionMessage = 'Exception message';
+        $e = new SmartlingApiException($exceptionMessage);
+
+        $this->assertTrue(is_string($e->getMessage()));
+        $this->assertNotEmpty($e->getMessage());
+        $this->assertSame($exceptionMessage, $e->getMessage());
+    }
+
+    /**
+     * Check exception's constructor with array of errors passed in.
+     */
+    public function testConstructorArrayMessage() {
+        $exceptionArray = [
+            'errors' => [
+                [
+                    'key' => 'error_key',
+                    'message' => 'Error message.',
+                    'details' => [
+                        'errorId' => 'error_id',
+                    ],
+                ],
+            ],
+        ];
+        $e = new SmartlingApiException($exceptionArray);
+
+        $this->assertTrue(is_string($e->getMessage()));
+        $this->assertNotEmpty($e->getMessage());
+        $this->assertSame(print_r($exceptionArray, TRUE), $e->getMessage());
+    }
+
+}
diff --git a/api-sdk-php/tests/unit/FileApiTest.php b/api-sdk-php/tests/unit/FileApiTest.php
old mode 100644
new mode 100755
index 0506f74..02a35ff
--- a/api-sdk-php/tests/unit/FileApiTest.php
+++ b/api-sdk-php/tests/unit/FileApiTest.php
@@ -866,4 +866,43 @@ class FileApiTest extends ApiTestAbstract
 
         $this->assertEquals('stream', get_resource_type($stream));
     }
+
+    /**
+     * Test async response with ACCEPTED code.
+     *
+     * It should not throw "Bad response format" exception.
+     */
+    public function testAcceptResponse() {
+        $responseMock = $this->getMockBuilder('Guzzle\Message\ResponseInterface')
+            ->setMethods(
+                array_merge(
+                    self::$responseInterfaceMethods,
+                    self::$messageInterfaceMethods
+                )
+            )
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $responseMock->expects(self::any())
+            ->method('getStatusCode')
+            ->willReturn(202);
+
+        $responseMock->expects(self::any())
+            ->method('getBody')
+            ->willReturn($this->responseAsync);
+
+        $responseMock->expects(self::any())
+            ->method('json')
+            ->willReturn(
+                json_decode($this->responseAsync, true)
+            );
+
+        $this->client->expects(self::once())
+            ->method('request')
+            ->willReturn($responseMock);
+
+        // Just random api call to mock async response of 'send' method.
+        $this->object->renameFile('test.xml', 'new_test.xml');
+    }
+
 }
diff --git a/api-sdk-php/tests/unit/JobsApiTest.php b/api-sdk-php/tests/unit/JobsApiTest.php
deleted file mode 100644
index 0ca4a69..0000000
--- a/api-sdk-php/tests/unit/JobsApiTest.php
+++ /dev/null
@@ -1,341 +0,0 @@
-<?php
-
-namespace Smartling\Tests\Unit;
-
-use DateTime;
-use DateTimeZone;
-use Smartling\Jobs\JobsApi;
-use Smartling\Jobs\Params\AddFileToJobParameters;
-use Smartling\Jobs\Params\CancelJobParameters;
-use Smartling\Jobs\Params\CreateJobParameters;
-use Smartling\Jobs\Params\ListJobsParameters;
-use Smartling\Jobs\Params\SearchJobsParameters;
-use Smartling\Jobs\Params\UpdateJobParameters;
-
-/**
- * Test class for Smartling\Jobs\JobsApi.
- */
-class JobsApiTest extends ApiTestAbstract
-{
-
-    /**
-     * Sets up the fixture, for example, opens a network connection.
-     * This method is called before a test is executed.
-     */
-    protected function setUp()
-    {
-        parent::setUp();
-        $this->prepareJobsApiMock();
-    }
-
-    private function prepareJobsApiMock()
-    {
-      $this->object = $this->getMockBuilder('Smartling\Jobs\JobsApi')
-        ->setMethods(NULL)
-        ->setConstructorArgs([
-          $this->projectId,
-          $this->client,
-          null,
-          JobsApi::ENDPOINT_URL,
-        ])
-        ->getMock();
-
-      $this->invokeMethod(
-        $this->object,
-        'setAuth',
-        [
-          $this->authProvider
-        ]
-      );
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::createJob
-     */
-    public function testCreateJob() {
-        $name = 'Test Job Name';
-        $description = 'Test Job Description';
-        $dueDate = DateTime::createFromFormat('Y-m-d H:i:s', '2020-01-01 19:19:17', new DateTimeZone('UTC'));
-        $locales = ['es', 'fr'];
-        $params = new CreateJobParameters();
-        $params->setName($name);
-        $params->setDescription($description);
-        $params->setDueDate($dueDate);
-        $params->setTargetLocales($locales);
-        $endpointUrl = vsprintf('%s/%s/jobs', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('post', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => FALSE,
-                'json' => [
-                    'jobName' => $name,
-                    'description' => $description,
-                    'dueDate' => $dueDate->format('Y-m-d\TH:i:s\Z'),
-                    'targetLocaleIds' => $locales,
-                ],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->createJob($params);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::updateJob
-     */
-    public function testUpdateJob() {
-        $jobId = 'Some job id';
-        $name = 'Test Job Name Updated';
-        $description = 'Test Job Description Updated';
-        $dueDate = DateTime::createFromFormat('Y-m-d H:i:s', '2030-01-01 19:19:17', new DateTimeZone('UTC'));
-        $params = new UpdateJobParameters();
-        $params->setName($name);
-        $params->setDescription($description);
-        $params->setDueDate($dueDate);
-        $endpointUrl = vsprintf('%s/%s/jobs/%s', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId,
-            $jobId,
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('put', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => FALSE,
-                'json' => [
-                    'jobName' => $name,
-                    'description' => $description,
-                    'dueDate' => $dueDate->format('Y-m-d\TH:i:s\Z'),
-                ],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->updateJob($jobId, $params);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::cancelJob
-     */
-    public function testCancelJob() {
-        $jobId = 'Some job id';
-        $reason = 'Some reason';
-        $params = new CancelJobParameters();
-        $params->setReason($reason);
-        $endpointUrl = vsprintf('%s/%s/jobs/%s/cancel', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId,
-            $jobId,
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('post', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => FALSE,
-                'json' => [
-                    'reason' => $reason,
-                ],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->cancelJob($jobId, $params);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::listJobs
-     */
-    public function testListJobs() {
-        $name = 'Test Job Name Updated';
-        $limit = 1;
-        $offset = 2;
-        $params = new ListJobsParameters();
-        $params->setName($name);
-        $params->setLimit($limit);
-        $params->setOffset($offset);
-        $endpointUrl = vsprintf('%s/%s/jobs', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId,
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('get', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => FALSE,
-                'query' => [
-                    'jobName' => $name,
-                    'limit' => $limit,
-                    'offset' => $offset,
-                ],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->listJobs($params);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::getJob
-     */
-    public function testGetJob() {
-        $jobId = 'Some job id';
-        $endpointUrl = vsprintf('%s/%s/jobs/%s', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId,
-            $jobId,
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('get', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => FALSE,
-                'query' => [],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->getJob($jobId);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::authorizeJob
-     */
-    public function testAuthorizeJob() {
-        $jobId = 'Some job id';
-        $endpointUrl = vsprintf('%s/%s/jobs/%s/authorize', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId,
-            $jobId,
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('post', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                    'Content-Type' => 'application/json',
-                ],
-                'exceptions' => FALSE,
-                'form_params' => [],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->authorizeJob($jobId);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::addFileToJob
-     */
-    public function testAddFileToJob() {
-        $jobId = 'Some job id';
-        $fileUri = 'some_file.xml';
-        $params = new AddFileToJobParameters();
-        $params->setFileUri($fileUri);
-        $endpointUrl = vsprintf('%s/%s/jobs/%s/file/add', [
-            JobsApi::ENDPOINT_URL,
-            $this->projectId,
-            $jobId,
-        ]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('post', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => FALSE,
-                'json' => [
-                    'fileUri' => $fileUri,
-                ],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->addFileToJob($jobId, $params);
-    }
-
-    /**
-     * @covers \Smartling\Jobs\JobsApi::searchJobs
-     */
-    public function testSearchJobs()
-    {
-        $fileToSearch = 'some_file_to_search.xml';
-        $params = new SearchJobsParameters();
-        $params->setFileUris([
-            $fileToSearch,
-        ]);
-
-        $endpointUrl = vsprintf('%s/%s/jobs/search', [JobsApi::ENDPOINT_URL, $this->projectId]);
-
-        $this->client
-            ->expects(self::once())
-            ->method('request')
-            ->with('post', $endpointUrl, [
-                'headers' => [
-                    'Accept' => 'application/json',
-                    'Authorization' => vsprintf('%s %s', [
-                        $this->authProvider->getTokenType(),
-                        $this->authProvider->getAccessToken(),
-                    ]),
-                ],
-                'exceptions' => false,
-                'json' => [
-                    'fileUris' => [
-                        $fileToSearch,
-                    ],
-                ],
-            ])
-            ->willReturn($this->responseMock);
-
-        $this->object->searchJobs($params);
-    }
-
-}
diff --git a/composer.json b/composer.json
index dc58940..75e95b4 100644
--- a/composer.json
+++ b/composer.json
@@ -6,6 +6,6 @@
     }
   ],
   "require": {
-    "smartling/api-sdk-php": "dev-3.0.0-g6"
+    "smartling/api-sdk-php": "3.0.7"
   }
 }
diff --git a/composer.lock b/composer.lock
index f770719..10c3ed9 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "content-hash": "6f835b24ead4c15426285a82a8c5ce44",
+    "content-hash": "eff8e31def3bbe45cc4aaf9e5a605c95",
     "packages": [
         {
             "name": "psr/log",
@@ -55,11 +55,11 @@
         },
         {
             "name": "smartling/api-sdk-php",
-            "version": "dev-3.0.0-g6",
+            "version": "3.0.7.0",
             "dist": {
                 "type": "path",
                 "url": "api-sdk-php",
-                "reference": "62668ffe27fb39ec35fb261ace01c81322e45ab9",
+                "reference": "f0b7ab1557955c1e648a9e34484483a0e6121b6c",
                 "shasum": null
             },
             "require": {
@@ -97,9 +97,7 @@
     "packages-dev": [],
     "aliases": [],
     "minimum-stability": "stable",
-    "stability-flags": {
-        "smartling/api-sdk-php": 20
-    },
+    "stability-flags": [],
     "prefer-stable": false,
     "prefer-lowest": false,
     "platform": [],
diff --git a/src/Context/ContextUploader.php b/src/Context/ContextUploader.php
index 4ced03c..c831321 100644
--- a/src/Context/ContextUploader.php
+++ b/src/Context/ContextUploader.php
@@ -8,6 +8,7 @@ use Exception;
 use Psr\Log\LoggerInterface;
 use Drupal\tmgmt_smartling\Exceptions\SmartlingBaseException;
 use Smartling\Context\Params\UploadContextParameters;
+use Smartling\Context\Params\UploadResourceParameters;
 use Smartling\Exceptions\SmartlingApiException;
 
 class ContextUploader {
@@ -88,15 +89,17 @@ class ContextUploader {
       throw new EmptyContextParameterException('Context url must be a non-empty field.');
     }
 
+    $smartling_context_directory = $proj_settings['scheme'] . '://tmgmt_smartling_context';
+    $smartling_context_file = $smartling_context_directory . '/' . str_replace('.', '_', $filename) . '.html';
+
+    // Upload context body.
     try {
       $html = $this->getContextualizedPage($url, $proj_settings);
 
       // Save context file.
-      $path = $proj_settings['scheme'] . '://tmgmt_smartling_context/' . str_replace('.', '_', $filename) . '.html';
-      $dirname = dirname($path);
-
-      if (file_prepare_directory($dirname, FILE_CREATE_DIRECTORY) && ($file = file_save_data($html, $path, FILE_EXISTS_REPLACE))) {
+      if (file_prepare_directory($smartling_context_directory, FILE_CREATE_DIRECTORY) && ($file = file_save_data($html, $smartling_context_file, FILE_EXISTS_REPLACE))) {
         $response = $this->uploadContextBody($file, $proj_settings);
+        $this->uploadContextMissingResources($smartling_context_directory, $proj_settings);
 
         if (!empty($response)) {
           $this->logger->info('Context upload for file @filename completed successfully.', ['@filename' => $filename]);
@@ -104,7 +107,7 @@ class ContextUploader {
       }
       else {
         $this->logger->error("Can't save context file: @path", [
-          '@path' => $path,
+          '@path' => $smartling_context_file,
         ]);
       }
     } catch (SmartlingApiException $e) {
@@ -144,8 +147,7 @@ class ContextUploader {
       $params->setName($file->getFileName());
 
       $api = $this->getApi($proj_settings, 'context');
-      $response = $api->uploadContext($params);
-      $response = $api->matchContext($response['contextUid']);
+      $response = $api->uploadAndMatchContext($params);
     } catch (Exception $e) {
       $response = [];
       watchdog_exception('tmgmt_smartling', $e);
@@ -155,6 +157,111 @@ class ContextUploader {
   }
 
   /**
+   * @param $smartling_context_directory
+   * @param $proj_settings
+   */
+  protected function uploadContextMissingResources($smartling_context_directory, $proj_settings) {
+    // Cache for resources which we can't upload. Do not try to re-upload them
+    // for 1 hour. After 1 hour cache will be reset and we will try again.
+    $cache_name = 'smartling_context_resources_cache';
+    $time_to_live = 60 * 60;
+    $cache = \Drupal::cache()->get($cache_name);
+    $cached_data = empty($cache) ? [] : $cache->data;
+    $update_cache = FALSE;
+    $smartling_context_resources_directory = $smartling_context_directory . '/resources';
+
+    // Do nothing if directory for resources isn't accessible.
+    if (!file_prepare_directory($smartling_context_resources_directory, FILE_CREATE_DIRECTORY)) {
+      $this->logger->error("Context resources directory @dir doesn't exist or is not writable. Missing resources were not uploaded. Context might look incomplete.", [
+        '@dir' => $smartling_context_directory,
+      ]);
+
+      return;
+    }
+
+    try {
+      global $base_url;
+
+      $api = $this->getApi($proj_settings, 'context');
+      $all_missing_resources = $api->getAllMissingResources();
+
+      // Method getAllMissingResources can return not all missing resources
+      // in case it took to much time. Log this information.
+      if (!$all_missing_resources['all']) {
+        $this->logger->warning('Not all missing context resources are received. Context might look incomplete.');
+      }
+
+      // Walk through missing resources and try to upload them.
+      foreach ($all_missing_resources['items'] as $item) {
+        // Handle situation when we have a resource with relative path.
+        if (strpos($item['url'], 'http://') === FALSE &&
+          strpos($item['url'], 'https://') === FALSE
+        ) {
+          $item['url'] = $base_url . '/' . ltrim($item['url'], '/');
+        }
+
+        // If current resource isn't in the cache and it's accessible then
+        // it means we can try to upload it.
+        if (!in_array($item['resourceId'], $cached_data) && $this->assetInliner->remote_file_exists($item['url'], $proj_settings)) {
+          $smartling_context_resource_file = $smartling_context_resources_directory . '/' . $item['resourceId'];
+          $smartling_context_resource_file_content = $this->assetInliner->getUrlContents($item['url'],
+            0,
+            'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10',
+            $proj_settings
+          );
+
+          // Ensure that resources directory is accessible, resource
+          // downloaded properly and only then upload it. ContextAPI will not
+          // be able to fopen() resource which is behind basic auth. So
+          // download it first (with a help of curl), save it to smartling's
+          // directory and then upload.
+          if ($file = file_save_data($smartling_context_resource_file_content, $smartling_context_resource_file, FILE_EXISTS_REPLACE)) {
+            $stream_wrapper_manager = \Drupal::service('stream_wrapper_manager')->getViaUri($file->getFileUri());
+            $params = new UploadResourceParameters();
+            $params->setFile($stream_wrapper_manager->realpath());
+            $is_resource_uploaded = $api->uploadResource($item['resourceId'], $params);
+
+            // Resource isn't uploaded for some reason. Log this info and set
+            // resource id into the cache. We will not try to upload this
+            // resource for the next hour.
+            if (!$is_resource_uploaded) {
+              $update_cache = TRUE;
+              $cached_data[] = $item['resourceId'];
+
+              $this->logger->warning("Can't upload context resource file with id = @id and url = @url. Context might look incomplete.", [
+                '@id' => $item['resourceId'],
+                '@url' => $item['url'],
+              ]);
+            }
+          }
+          // We can't save context resource file. Log this info.
+          else {
+            $this->logger->error("Can't save context resource file: @path", [
+              '@path' => $smartling_context_resource_file,
+            ]);
+          }
+        }
+        else {
+          // Current resource isn't accessible (or already in the cache).
+          // If first case then add inaccessible resource into the cache.
+          if (!in_array($item['resourceId'], $cached_data)) {
+            $update_cache = TRUE;
+            $cached_data[] = $item['resourceId'];
+          }
+        }
+      }
+
+      // Set failed resources into the cache for the next hour.
+      if ($update_cache) {
+        \Drupal::cache()->set($cache_name, $cached_data, time() + $time_to_live);
+      }
+    }
+    catch (Exception $e) {
+      watchdog_exception('tmgmt_smartling', $e);
+    }
+  }
+
+  /**
    * @param $filename
    * @return bool
    */
diff --git a/src/Context/HtmlAssetInliner.php b/src/Context/HtmlAssetInliner.php
index 1e5d662..2c049d7 100644
--- a/src/Context/HtmlAssetInliner.php
+++ b/src/Context/HtmlAssetInliner.php
@@ -170,7 +170,7 @@ class HtmlAssetInliner {
    *
    * @return bool
    */
-  private function remote_file_exists($url) {
+  public function remote_file_exists($url, $proj_settings) {
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     # don't download content
@@ -178,6 +178,8 @@ class HtmlAssetInliner {
     curl_setopt($ch, CURLOPT_FAILONERROR, 1);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 
+    $this->applySettingsToCurl($proj_settings, $ch);
+
     if (curl_exec($ch) !== FALSE) {
       return TRUE;
     }
@@ -318,7 +320,7 @@ class HtmlAssetInliner {
    *
    * @return int|mixed
    */
-  private function getUrlContents(
+  public function getUrlContents(
     $url,
     $timeout = 0,
     $userAgent = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10',
@@ -335,14 +337,7 @@ class HtmlAssetInliner {
       curl_setopt($crl, CURLOPT_HEADER, 1);
     }
 
-    if (!empty($settings['context_skip_host_verifying'])) {
-      curl_setopt($crl, CURLOPT_SSL_VERIFYHOST, FALSE);
-    }
-
-    if (!empty($settings['enable_basic_auth'])) {
-      curl_setopt($crl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
-      curl_setopt($crl, CURLOPT_USERPWD, $settings['basic_auth']['login'] . ':' . $settings['basic_auth']['password']);
-    }
+    $this->applySettingsToCurl($settings, $crl);
 
     curl_setopt($crl, CURLOPT_URL, $url);
     curl_setopt($crl, CURLOPT_RETURNTRANSFER, 1); # return result as string rather than direct output
@@ -382,6 +377,21 @@ class HtmlAssetInliner {
   }
 
   /**
+   * @param $proj_settings
+   * @param $curl
+   */
+  private function applySettingsToCurl($proj_settings, $curl) {
+    if (!empty($proj_settings['context_skip_host_verifying'])) {
+      curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
+    }
+
+    if (!empty($proj_settings['enable_basic_auth'])) {
+      curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+      curl_setopt($curl, CURLOPT_USERPWD, $proj_settings['basic_auth']['login'] . ':' . $proj_settings['basic_auth']['password']);
+    }
+  }
+
+  /**
    * Converts relative URLs to absolute URLs
    *
    * @param $url
diff --git a/vendor/autoload.php b/vendor/autoload.php
index 1d4d2a7..bb163ab 100644
--- a/vendor/autoload.php
+++ b/vendor/autoload.php
@@ -4,4 +4,4 @@
 
 require_once __DIR__ . '/composer/autoload_real.php';
 
-return ComposerAutoloaderInitc7c7f4b7f4e32502db73aa4d7eff81a4::getLoader();
+return ComposerAutoloaderInit8b5d022db0ea826d55cbf445448023ae::getLoader();
diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php
index 2c21373..6ff6a18 100644
--- a/vendor/composer/autoload_real.php
+++ b/vendor/composer/autoload_real.php
@@ -2,7 +2,7 @@
 
 // autoload_real.php @generated by Composer
 
-class ComposerAutoloaderInitc7c7f4b7f4e32502db73aa4d7eff81a4
+class ComposerAutoloaderInit8b5d022db0ea826d55cbf445448023ae
 {
     private static $loader;
 
@@ -19,15 +19,15 @@ class ComposerAutoloaderInitc7c7f4b7f4e32502db73aa4d7eff81a4
             return self::$loader;
         }
 
-        spl_autoload_register(array('ComposerAutoloaderInitc7c7f4b7f4e32502db73aa4d7eff81a4', 'loadClassLoader'), true, true);
+        spl_autoload_register(array('ComposerAutoloaderInit8b5d022db0ea826d55cbf445448023ae', 'loadClassLoader'), true, true);
         self::$loader = $loader = new \Composer\Autoload\ClassLoader();
-        spl_autoload_unregister(array('ComposerAutoloaderInitc7c7f4b7f4e32502db73aa4d7eff81a4', 'loadClassLoader'));
+        spl_autoload_unregister(array('ComposerAutoloaderInit8b5d022db0ea826d55cbf445448023ae', 'loadClassLoader'));
 
         $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
         if ($useStaticLoader) {
             require_once __DIR__ . '/autoload_static.php';
 
-            call_user_func(\Composer\Autoload\ComposerStaticInitc7c7f4b7f4e32502db73aa4d7eff81a4::getInitializer($loader));
+            call_user_func(\Composer\Autoload\ComposerStaticInit8b5d022db0ea826d55cbf445448023ae::getInitializer($loader));
         } else {
             $map = require __DIR__ . '/autoload_namespaces.php';
             foreach ($map as $namespace => $path) {
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 3fc16e6..1df124f 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -4,7 +4,7 @@
 
 namespace Composer\Autoload;
 
-class ComposerStaticInitc7c7f4b7f4e32502db73aa4d7eff81a4
+class ComposerStaticInit8b5d022db0ea826d55cbf445448023ae
 {
     public static $prefixLengthsPsr4 = array (
         'S' => 
@@ -31,8 +31,8 @@ class ComposerStaticInitc7c7f4b7f4e32502db73aa4d7eff81a4
     public static function getInitializer(ClassLoader $loader)
     {
         return \Closure::bind(function () use ($loader) {
-            $loader->prefixLengthsPsr4 = ComposerStaticInitc7c7f4b7f4e32502db73aa4d7eff81a4::$prefixLengthsPsr4;
-            $loader->prefixDirsPsr4 = ComposerStaticInitc7c7f4b7f4e32502db73aa4d7eff81a4::$prefixDirsPsr4;
+            $loader->prefixLengthsPsr4 = ComposerStaticInit8b5d022db0ea826d55cbf445448023ae::$prefixLengthsPsr4;
+            $loader->prefixDirsPsr4 = ComposerStaticInit8b5d022db0ea826d55cbf445448023ae::$prefixDirsPsr4;
 
         }, null, ClassLoader::class);
     }
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index 905d419..ceaa1e3 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -50,12 +50,12 @@
     },
     {
         "name": "smartling/api-sdk-php",
-        "version": "dev-3.0.0-g6",
-        "version_normalized": "dev-3.0.0-g6",
+        "version": "3.0.7.0",
+        "version_normalized": "3.0.7.0",
         "dist": {
             "type": "path",
             "url": "api-sdk-php",
-            "reference": "62668ffe27fb39ec35fb261ace01c81322e45ab9",
+            "reference": "f0b7ab1557955c1e648a9e34484483a0e6121b6c",
             "shasum": null
         },
         "require": {
