diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php
index 9228c71ccbf54883b3b8696b3003b1c7e0781b16..082e6188379be59d6caf877b93c5fb2c5d7fbdb2 100644
--- a/htdocs/api/class/api.class.php
+++ b/htdocs/api/class/api.class.php
@@ -19,6 +19,7 @@
 use Luracast\Restler\Restler;
 use Luracast\Restler\RestException;
 use Luracast\Restler\Defaults;
+use Luracast\Restler\Format\UploadFormat;
 
 require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
 
@@ -47,14 +48,14 @@ class DolibarrApi
     function __construct($db, $cachedir='')
     {
         global $conf;
-        
+
         if (empty($cachedir)) $cachedir = $conf->api->dir_temp;
         Defaults::$cacheDirectory = $cachedir;
-        
+
         $this->db = $db;
         $production_mode = ( empty($conf->global->API_PRODUCTION_MODE) ? false : true );
         $this->r = new Restler($production_mode);
-        
+
         $this->r->setAPIVersion(1);
     }
 
@@ -86,21 +87,23 @@ class DolibarrApi
 
         // Remove $db object property for object
         unset($object->db);
-        
+
         // Remove linkedObjects. We should already have linkedObjectIds that avoid huge responses
         unset($object->linkedObjects);
+
+        unset($object->lines); // should be ->lines
         
         unset($object->fields);
         
         unset($object->oldline);
-        
+
         unset($object->error);
         unset($object->errors);
-        
+
         unset($object->ref_previous);
         unset($object->ref_next);
         unset($object->ref_int);
-        
+
         unset($object->projet);     // Should be fk_project
         unset($object->project);    // Should be fk_project
         unset($object->author);     // Should be fk_user_author
@@ -112,18 +115,18 @@ class DolibarrApi
         unset($object->timespent_withhour);
         unset($object->timespent_fk_user);
         unset($object->timespent_note);
-        
+
         unset($object->statuts);
         unset($object->statuts_short);
         unset($object->statuts_logo);
         unset($object->statuts_long);
-        
+
         unset($object->element);
         unset($object->fk_element);
         unset($object->table_element);
         unset($object->table_element_line);
         unset($object->picto);
-        
+
         // Remove the $oldcopy property because it is not supported by the JSON
         // encoder. The following error is generated when trying to serialize
         // it: "Error encoding/decoding JSON: Type is not supported"
@@ -153,7 +156,7 @@ class DolibarrApi
                 }
             }
         }*/
-        
+
 		return $object;
     }
 
@@ -188,12 +191,12 @@ class DolibarrApi
 
 		return checkUserAccessToObject(DolibarrApiAccess::$user, $featuresarray, $resource_id, $dbtablename, $feature2, $dbt_keyfield, $dbt_select);
 	}
-	
+
 	/**
 	 * Return if a $sqlfilters parameter is valid
-	 * 
+	 *
 	 * @param  string   $sqlfilters     sqlfilter string
-	 * @return boolean                  True if valid, False if not valid 
+	 * @return boolean                  True if valid, False if not valid
 	 */
 	function _checkFilters($sqlfilters)
 	{
@@ -217,22 +220,22 @@ class DolibarrApi
 	    }
 	    return true;
 	}
-	
+
 	/**
 	 * Function to forge a SQL criteria
-	 * 
+	 *
 	 * @param  array    $matches       Array of found string by regex search
 	 * @return string                  Forged criteria. Example: "t.field like 'abc%'"
 	 */
 	static function _forge_criteria_callback($matches)
 	{
 	    global $db;
-	    
+
 	    //dol_syslog("Convert matches ".$matches[1]);
 	    if (empty($matches[1])) return '';
 	    $tmp=explode(':',$matches[1]);
         if (count($tmp) < 3) return '';
-        
+
 	    $tmpescaped=$tmp[2];
 	    if (preg_match('/^\'(.*)\'$/', $tmpescaped, $regbis))
 	    {
@@ -243,5 +246,5 @@ class DolibarrApi
 	        $tmpescaped = $db->escape($tmpescaped);
 	    }
 	    return $db->escape($tmp[0]).' '.strtoupper($db->escape($tmp[1]))." ".$tmpescaped;
-	}	
+	}
 }
diff --git a/htdocs/api/class/api_documents.class.php b/htdocs/api/class/api_documents.class.php
new file mode 100644
index 0000000000000000000000000000000000000000..ca10b2befce87fe5ff2d8626dd1c9b281f32f5da
--- /dev/null
+++ b/htdocs/api/class/api_documents.class.php
@@ -0,0 +1,143 @@
+<?php
+/* Copyright (C) 2016   Xebax Christy           <xebax@wanadoo.fr>
+ * Copyright (C) 2016	Laurent Destailleur		<eldy@users.sourceforge.net>
+ * Copyright (C) 2016   Jean-François Ferry     <jfefe@aternatik.fr>
+ *
+ * This program is free software you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+use Luracast\Restler\RestException;
+use Luracast\Restler\Format\UploadFormat;
+
+
+require_once DOL_DOCUMENT_ROOT.'/main.inc.php';
+
+/**
+ * API class for receive files
+ *
+ * @access protected
+ * @class Documents {@requires user,external}
+ */
+class Documents extends DolibarrApi
+{
+
+    /**
+     * @var array   $DOCUMENT_FIELDS     Mandatory fields, checked when create and update object
+     */
+    static $DOCUMENT_FIELDS = array(
+        'name',
+        'modulepart',
+        'file'
+    );
+
+    /**
+     * Constructor
+     */
+    function __construct()
+    {
+        global $db;
+        $this->db = $db;
+    }
+
+    /**
+     * Return a document
+     *
+     * @param   string  $module_part    Module part for file
+     * @param   string  $filename       File name
+     *
+     * @return array
+     * @throws RestException
+     *
+     */
+     public function get($module_part, $filename) {
+
+     }
+
+
+    /**
+     * Receive file
+     *
+     * @param   array   $request_data   Request datas
+     *
+     * @return  bool     State of copy
+     * @throws RestException
+     */
+    public function post($request_data) {
+        global $conf;
+        
+        require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
+
+        if (!DolibarrApiAccess::$user->rights->ecm->upload) {
+            throw new RestException(401);
+        }
+
+        // Suppression de la chaine de caractere ../ dans $original_file
+		$original_file = str_replace("../","/", $request_data['name']);
+        $refname = str_replace("../","/", $request_data['refname']);
+
+		// find the subdirectory name as the reference
+		if (empty($request_data['refname'])) $refname=basename(dirname($original_file)."/");
+
+        // Security:
+		// On interdit les remontees de repertoire ainsi que les pipe dans
+		// les noms de fichiers.
+		if (preg_match('/\.\./',$original_file) || preg_match('/[<>|]/',$original_file))
+		{
+            throw new RestException(401,'Refused to deliver file '.$original_file);
+		}
+        if (preg_match('/\.\./',$refname) || preg_match('/[<>|]/',$refname))
+		{
+            throw new RestException(401,'Refused to deliver file '.$refname);
+		}
+
+        $modulepart = $request_data['modulepart'];
+
+        // Check mandatory fields
+        $result = $this->_validate_file($request_data);
+
+        $upload_dir = DOL_DATA_ROOT . '/' .$modulepart.'/'.dol_sanitizeFileName($refname);
+        $destfile = $upload_dir . $original_file;
+
+        if (!is_dir($upload_dir)) {
+            throw new RestException(401,'Directory not exists : '.$upload_dir);
+        }
+
+        $file = $_FILES['file'];
+        $srcfile = $file['tmp_name'];
+        $res = dol_move($srcfile, $destfile, 0, 1);
+
+        if (!$res) {
+            throw new RestException(500);
+        }
+
+        return $res;
+    }
+
+    /**
+     * Validate fields before create or update object
+     *
+     * @param   array           $data   Array with data to verify
+     * @return  array
+     * @throws  RestException
+     */
+    function _validate_file($data) {
+        $result = array();
+        foreach (Documents::$DOCUMENT_FIELDS as $field) {
+            if (!isset($data[$field]))
+                throw new RestException(400, "$field field missing");
+            $result[$field] = $data[$field];
+        }
+        return $result;
+    }
+}
diff --git a/htdocs/api/index.php b/htdocs/api/index.php
index 37be4d8cc26330410cd955a224d4ded133b79978..fa96da6b139346db5e8c57a46ba60fbb5a678567 100644
--- a/htdocs/api/index.php
+++ b/htdocs/api/index.php
@@ -66,16 +66,18 @@ if (preg_match('/api\/index\.php\/explorer/', $_SERVER["PHP_SELF"]) && ! empty($
 }
 
 
-
 $api = new DolibarrApi($db);
 
 // Enable the Restler API Explorer.
 // See https://github.com/Luracast/Restler-API-Explorer for more info.
 $api->r->addAPIClass('Luracast\\Restler\\Explorer');
 
-$api->r->setSupportedFormats('JsonFormat', 'XmlFormat');
+$api->r->setSupportedFormats('JsonFormat', 'XmlFormat', 'UploadFormat');
 $api->r->addAuthenticationClass('DolibarrApiAccess','');
 
+// Define accepted mime types
+UploadFormat::$allowedMimeTypes = array('image/jpeg', 'image/png', 'text/plain', 'application/octet-stream');
+
 $listofapis = array();
 
 $modulesdir = dolGetModulesDirs();
@@ -96,7 +98,7 @@ foreach ($modulesdir as $dir)
                 $module = strtolower($reg[1]);
                 $moduledirforclass = $module;
                 $moduleforperm = $module;
-                
+
                 if ($module == 'propale') {
                     $moduledirforclass = 'comm/propal';
                     $moduleforperm='propal';
@@ -129,7 +131,7 @@ foreach ($modulesdir as $dir)
                     $moduledirforclass = 'fourn';
                 }
                 //dol_syslog("Found module file ".$file." - module=".$module." - moduledirforclass=".$moduledirforclass);
-                
+
                 // Defined if module is enabled
                 $enabled=true;
                 if (empty($conf->$moduleforperm->enabled)) $enabled=false;
@@ -152,7 +154,7 @@ foreach ($modulesdir as $dir)
                         while (($file_searched = readdir($handle_part))!==false)
                         {
                             if ($file_searched == 'api_access.class.php') continue;
-                            
+
                             // Support of the deprecated API.
                             if (is_readable($dir_part.$file_searched) && preg_match("/^api_deprecated_(.*)\.class\.php$/i",$file_searched,$reg))
                             {
diff --git a/test/phpunit/RestAPIDocumentTest.php b/test/phpunit/RestAPIDocumentTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..ea0c218027fc35490650b1a8b23afc3043b5e4bc
--- /dev/null
+++ b/test/phpunit/RestAPIDocumentTest.php
@@ -0,0 +1,183 @@
+<?php
+/* Copyright (C) 2010 Laurent Destailleur  <eldy@users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * or see http://www.gnu.org/
+ */
+
+/**
+ *      \file       test/phpunit/RestAPIDocumentTest.php
+ *      \ingroup    test
+ *      \brief      PHPUnit test
+ *      \remarks    To run this script as CLI:  phpunit filename.php.
+ */
+global $conf,$user,$langs,$db;
+//define('TEST_DB_FORCE_TYPE','mysql');	// This is to force using mysql driver
+//require_once 'PHPUnit/Autoload.php';
+require_once dirname(__FILE__).'/../../htdocs/master.inc.php';
+require_once dirname(__FILE__).'/../../htdocs/core/lib/date.lib.php';
+require_once dirname(__FILE__).'/../../htdocs/core/lib/geturl.lib.php';
+
+if (empty($user->id)) {
+    echo "Load permissions for admin user nb 1\n";
+    $user->fetch(1);
+    $user->getrights();
+}
+$conf->global->MAIN_DISABLE_ALL_MAILS = 1;
+$conf->global->MAIN_UMASK = '0666';
+
+/**
+ * Class for PHPUnit tests.
+ *
+ * @backupGlobals disabled
+ * @backupStaticAttributes enabled
+ * @remarks	backupGlobals must be disabled to have db,conf,user and lang not erased.
+ */
+class RestAPIDocumentTest extends PHPUnit_Framework_TestCase
+{
+    protected $savconf;
+    protected $savuser;
+    protected $savlangs;
+    protected $savdb;
+    protected $api_url;
+    protected $api_key;
+
+    /**
+     * Constructor
+     * We save global variables into local variables.
+     *
+     * @return DateLibTest
+     */
+    public function __construct()
+    {
+        //$this->sharedFixture
+        global $conf,$user,$langs,$db;
+        $this->savconf = $conf;
+        $this->savuser = $user;
+        $this->savlangs = $langs;
+        $this->savdb = $db;
+
+        echo __METHOD__.' db->type='.$db->type.' user->id='.$user->id;
+        //print " - db ".$db->db;
+        echo "\n";
+    }
+
+    // Static methods
+    public static function setUpBeforeClass()
+    {
+        global $conf,$user,$langs,$db;
+        $db->begin(); // This is to have all actions inside a transaction even if test launched without suite.
+
+        echo __METHOD__."\n";
+    }
+
+    // tear down after class
+    public static function tearDownAfterClass()
+    {
+        global $conf,$user,$langs,$db;
+        $db->rollback();
+
+        echo __METHOD__."\n";
+    }
+
+    /**
+     * Init phpunit tests.
+     */
+    protected function setUp()
+    {
+        global $conf,$user,$langs,$db;
+        $conf = $this->savconf;
+        $user = $this->savuser;
+        $langs = $this->savlangs;
+        $db = $this->savdb;
+
+        $this->api_url = DOL_MAIN_URL_ROOT.'/api/index.php';
+
+        $login = 'admin';
+        $password = 'admin';
+        $url = $this->api_url.'/login?login='.$login.'&password='.$password;
+        // Call the API login method to save api_key for this test class
+        $result = getURLContent($url, 'GET', '', 1, array());
+        echo __METHOD__.' result = '.var_export($result, true)."\n";
+        echo __METHOD__.' curl_error_no: '.$result['curl_error_no']."\n";
+        $this->assertEquals($result['curl_error_no'], '');
+        $object = json_decode($result['content'], true);
+        $this->assertNotNull($object, 'Parsing of json result must no be null');
+        $this->assertEquals('200', $object['success']['code']);
+
+        $this->api_key = $object['success']['token'];
+        echo __METHOD__." api_key: $this->api_key \n";
+
+        echo __METHOD__."\n";
+    }
+
+    /**
+     * End phpunit tests.
+     */
+    protected function tearDown()
+    {
+        echo __METHOD__."\n";
+    }
+
+    /**
+     * testRestReceiveDocument.
+     *
+     * @return int
+     */
+    public function testRestReceiveDocument()
+    {
+        global $conf,$user,$langs,$db;
+
+        $url = $this->api_url.'/documents/?api_key='.$this->api_key;
+
+        $fileName = 'img250x20.png';
+        $filePath = dirname(__FILE__).'/'.$fileName;
+        $mimetype = mime_content_type($filePath);
+      // Init Curl file object
+      // See https://wiki.php.net/rfc/curl-file-upload
+      $cfile = curl_file_create($filePath, $mimetype);
+
+        echo __METHOD__.' Request POST url='.$url."\n";
+
+      // Send to existant directory
+      $data = array(
+          'modulepart' => 'facture',
+          'file' => $cfile,
+          'refname' => 'AV1303-0003',
+          'name' => $fileName, // Name for destination
+          'type' => $mimetype, );
+
+        $result = getURLContent($url, 'POST', $data, 1);
+
+        echo __METHOD__.' Result for sending document: '.var_export($result, true)."\n";
+        echo __METHOD__.' curl_error_no: '.$result['curl_error_no']."\n";
+        $this->assertEquals($result['curl_error_no'], '');
+        $this->assertEquals($result['content'], 'true');
+
+      // Send to unexistant directory
+      $data = array(
+          'modulepart' => 'facture',
+          'file' => $cfile,
+          'name' => 'AV1303-0003STSEIUDEISRESIJLEU/'.$fileName, // Name for destination
+          'type' => $mimetype, );
+
+        $result2 = getURLContent($url, 'POST', $data, 1);
+        echo __METHOD__.' Result for sending document: '.var_export($result2, true)."\n";
+        echo __METHOD__.' curl_error_no: '.$result['curl_error_no']."\n";
+
+        $object = json_decode($result2['content'], true);
+        $this->assertNotNull($object, 'Parsing of json result must no be null');
+        $this->assertEquals('401', $object['error']['code']);
+    }
+}