diff --git a/agavepy/agave.py b/agavepy/agave.py
index 26d0b79..b967bd8 100644
--- a/agavepy/agave.py
+++ b/agavepy/agave.py
@@ -25,8 +25,8 @@ from agavepy.clients import (clients_create, clients_delete, clients_list,
 from agavepy.tokens import token_create, refresh_token
 from agavepy.utils import load_config, save_config
 from agavepy.files import (files_copy, files_delete, files_download, 
-    files_history, files_list, files_mkdir, files_move, files_pems_delete, 
-    files_pems_list, files_pems_update, files_upload)
+    files_history, files_import, files_list, files_mkdir, files_move, 
+    files_pems_delete, files_pems_list, files_pems_update, files_upload)
 
 
 import sys
@@ -826,6 +826,19 @@ class Agave(object):
         files_history(self.api_server, self.token, path)
 
 
+    def files_import(self, source, destination):
+        """ Imports a remote URI to a remote storage system
+        
+        If 'source' is an agave source then prefix the uri with 'agave://'. For
+        example, source = 'agave://data-sd2e-community/test.txt'.
+        """
+        # Check if tokens need to be refreshed.
+        self.refresh_tokens()
+
+        # Import file.
+        files_import(self.api_server, self.token, source, destination)
+
+
     def files_list(self, system_path, long_format=False):
         """ List files on remote system
         """
diff --git a/agavepy/files/__init__.py b/agavepy/files/__init__.py
index 5aedd4e..5783bf1 100644
--- a/agavepy/files/__init__.py
+++ b/agavepy/files/__init__.py
@@ -2,6 +2,7 @@ from .copy import files_copy
 from .delete import files_delete
 from .download import files_download
 from .history import files_history
+from .import_files import files_import
 from .list import files_list
 from .mkdir import files_mkdir
 from .move import files_move
diff --git a/agavepy/files/import_files.py b/agavepy/files/import_files.py
new file mode 100644
index 0000000..cfdbe8d
--- /dev/null
+++ b/agavepy/files/import_files.py
@@ -0,0 +1,34 @@
+"""
+    import.py
+"""
+import requests
+from .exceptions import AgaveFilesError
+from ..utils import handle_bad_response_status_code
+
+
+def files_import(tenant_url, access_token, source, destination):
+    """ Imports a remote URI to a remote storage system
+
+    If 'source' is an agave source then prefix the uri with 'agave://'. For 
+    example, source = 'agave://data-sd2e-community/test.txt'.
+    """
+    # Set request url.
+    endpoint = "{0}/{1}/{2}".format(tenant_url, "files/v2/media/system", destination)
+
+    # Make request.
+    try:
+        # TODO: document the other fields.
+        data = {
+            "urlToIngest": source,
+            "notifications": "",
+            "fileType": "",
+            "fileName": "",
+        }
+        headers  = {"Authorization":"Bearer {0}".format(access_token)}
+        params   = {"pretty": "true"}
+        resp = requests.post(endpoint, headers=headers, data=data, params=params)
+    except Exception as err:
+        raise AgaveFilesError(err)
+
+    # Handle bad status code.
+    handle_bad_response_status_code(resp)
diff --git a/docs/docsite/files/files.rst b/docs/docsite/files/files.rst
index 82c46c2..6af157d 100644
--- a/docs/docsite/files/files.rst
+++ b/docs/docsite/files/files.rst
@@ -109,6 +109,23 @@ off:
     >>> agave.files_delete("data-tacc-user/somefile-or-directory")
 
 
+Import files from ther systems
+##############################
+
+It may be useful to import data from other storage systems, e.g. from the
+community data space to your private data space.
+The ``files_import`` method can be used for that purpose.
+
+.. code-block:: pycon
+
+    agave.files_import("agave://data-community/test.txt", "system-id/")
+
+Please also note that even though you are able to import files from other Agave
+storage systems, you may not always need to import those files.
+Also, note that the source, the first argument, must be an agave compliant uri
+by prefixing the system if and path convination with the string ``agave://``.
+
+
 Making a directory
 ##################
 

Implement files_import
**Is your feature request related to a problem? Please describe.**
Part of the changes proposed for release v3.0.0 of `TACC-Cloud/agave-cli`

**Describe the solution you'd like**
Implement a method to import a remote URI to a remote storage system.
diff --git a/tests/files_test.py b/tests/files_test.py
index d23a830..c6be1d1 100644
--- a/tests/files_test.py
+++ b/tests/files_test.py
@@ -77,7 +77,7 @@ class MockServerFilesEndpoints(BaseHTTPRequestHandler):
 
 
     def do_POST(self):
-        """ Upload file
+        """ Upload or import a file
 
         Save uploaded file to current working directory and send a response.
         """
@@ -97,29 +97,47 @@ class MockServerFilesEndpoints(BaseHTTPRequestHandler):
                 "CONTENT_TYPE": self.headers["Content-Type"]
             })
 
-        # Save uploaded file.
-        fname = form["fileToUpload"].filename
-        with open(fname, "wb") as flocal:
-            shutil.copyfileobj(form["fileToUpload"].file, flocal)
-
-        # Send response.
-        request_source = self.headers.get("HOST")
-        file_path      = "/".join(elements[5:] + [fname])
-        system_id      = elements[4]
-        request_url    = "".join(["https://tenant", self.path, "/", fname])
-        system_url     = "".join(["https://tenant", "/systems/v2/", system_id])
-        history_url    = "".join(["https://tenant", "/files/v2/history/system/", system_id, "/", file_path])
-        sample_files_upload_response["result"]["name"] = fname
-        sample_files_upload_response["result"]["source"] = request_source
-        sample_files_upload_response["result"]["path"] = file_path
-        sample_files_upload_response["result"]["systemId"] = system_id
-        sample_files_upload_response["result"]["_links"]["self"]["href"] = request_url
-        sample_files_upload_response["result"]["_links"]["system"]["href"] = system_url
-        sample_files_upload_response["result"]["_links"]["history"]["href"] = history_url
-        try: # python 2
-            self.wfile.write(json.dumps(sample_files_upload_response))
-        except TypeError:
-            self.wfile.write(json.dumps(sample_files_upload_response).encode())
+        # Check if request is for uploading or importing a file.
+        action = ""
+        if form.getvalue("fileToUpload", "") != "":
+            action = "upload"
+        elif form.getvalue("urlToIngest", "") != "":
+            action = "import"
+        else:
+            self.send_response(400)
+            self.end_headers()
+            return
+
+        if action == "upload":
+            # Save uploaded file.
+            fname = form["fileToUpload"].filename
+            with open(fname, "wb") as flocal:
+                shutil.copyfileobj(form["fileToUpload"].file, flocal)
+                
+            # Send response.
+            request_source = self.headers.get("HOST")
+            file_path      = "/".join(elements[5:] + [fname])
+            system_id      = elements[4]
+            request_url    = "".join(["https://tenant", self.path, "/", fname])
+            system_url     = "".join(["https://tenant", "/systems/v2/", system_id])
+            history_url    = "".join(["https://tenant", "/files/v2/history/system/", system_id, "/", file_path])
+            sample_files_upload_response["result"]["name"] = fname
+            sample_files_upload_response["result"]["source"] = request_source
+            sample_files_upload_response["result"]["path"] = file_path
+            sample_files_upload_response["result"]["systemId"] = system_id
+            sample_files_upload_response["result"]["_links"]["self"]["href"] = request_url
+            sample_files_upload_response["result"]["_links"]["system"]["href"] = system_url
+            sample_files_upload_response["result"]["_links"]["history"]["href"] = history_url
+            
+            try: # python 2
+                self.wfile.write(json.dumps(sample_files_upload_response))
+            except TypeError:
+                self.wfile.write(json.dumps(sample_files_upload_response).encode())
+        
+        elif action == "import":
+            self.send_response(200)
+            self.end_headers()
+            return
 
 
     def do_PUT(self):
@@ -241,6 +259,8 @@ class TestMockServer(MockServer):
             local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
             agave = Agave(api_server=local_uri)
             agave.token = "mock-access-token"
+            agave.created_at = str(int(time.time()))
+            agave.expires_in = str(14400)
 
             agave.files_download("tacc-globalfs-user/"+tmp_file, local_file)
         finally:
@@ -264,6 +284,8 @@ class TestMockServer(MockServer):
             local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
             agave = Agave(api_server=local_uri)
             agave.token = "mock-access-token"
+            agave.created_at = str(int(time.time()))
+            agave.expires_in = str(14400)
 
             agave.files_upload(tmp_file, "tacc-globalfs-user/")
         finally:
@@ -286,6 +308,8 @@ class TestMockServer(MockServer):
             local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
             agave = Agave(api_server=local_uri)
             agave.token = "mock-access-token"
+            agave.created_at = str(int(time.time()))
+            agave.expires_in = str(14400)
 
             agave.files_delete("tacc-globalfs-user/"+tmp_file)
         finally:
@@ -305,6 +329,8 @@ class TestMockServer(MockServer):
         local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
         agave = Agave(api_server=local_uri)
         agave.token = "mock-access-token"
+        agave.created_at = str(int(time.time()))
+        agave.expires_in = str(14400)
         
         agave.files_copy("tacc-globalfs/file", "tacc-globalfs/file-copy")
 
@@ -318,6 +344,8 @@ class TestMockServer(MockServer):
         local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
         agave = Agave(api_server=local_uri)
         agave.token = "mock-access-token"
+        agave.created_at = str(int(time.time()))
+        agave.expires_in = str(14400)
 
         agave.files_copy("tacc-globalfs/file", "tacc-globalfs/another-file")
 
@@ -331,5 +359,22 @@ class TestMockServer(MockServer):
         local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
         agave = Agave(api_server=local_uri)
         agave.token = "mock-access-token"
+        agave.created_at = str(int(time.time()))
+        agave.expires_in = str(14400)
 
         agave.files_mkdir("tacc-globalfs/new/path")
+
+
+    def test_files_import(self, capfd):
+        """ Test files import
+        """
+        local_uri = "http://localhost:{port}/".format(port=self.mock_server_port)
+        agave = Agave(api_server=local_uri)
+        agave.token = "mock-access-token"
+        agave.created_at = str(int(time.time()))
+        agave.expires_in = str(14400)
+
+        # Import file.
+        agave.files_import("agave://data-sd2e-community/test.txt", "tacc-globalfs-username/")
+        out, err = capfd.readouterr()
+        assert "200" in err

pip install -e .
parse_log_pytest
requirements.txt
pytest
apt-get update apt-get install -y gcc
3.6
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
-e git+https://github.com/TACC/agavepy.git@06a9114a77ab4ff8af368e9c3f750c6500e3af3e#egg=agavepy
attrs==22.2.0
backports.ssl-match-hostname==3.7.0.1
certifi==2021.5.30
charset-normalizer==2.0.12
cloudpickle==2.2.1
configparser==5.2.0
future==1.0.0
idna==3.10
importlib-metadata==4.8.3
iniconfig==1.1.1
Jinja2==3.0.3
MarkupSafe==2.0.1
packaging==21.3
pluggy==1.0.0
py==1.11.0
pyparsing==3.1.4
pytest==7.0.1
python-dateutil==2.9.0.post0
requests==2.27.1
requests-toolbelt==1.0.0
six==1.17.0
tomli==1.2.3
typing_extensions==4.1.1
urllib3==1.26.20
websocket-client==0.53.0
zipp==3.6.0

name: agavepy
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - certifi=2021.5.30=py36h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.3=he6710b0_2
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=1.1.1w=h7f8727e_0
  - pip=21.2.2=py36h06a4308_0
  - python=3.6.13=h12debd9_1
  - readline=8.2=h5eee18b_0
  - setuptools=58.0.4=py36h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.37.1=pyhd3eb1b0_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - attrs==22.2.0
      - backports-ssl-match-hostname==3.7.0.1
      - charset-normalizer==2.0.12
      - cloudpickle==2.2.1
      - configparser==5.2.0
      - future==1.0.0
      - idna==3.10
      - importlib-metadata==4.8.3
      - iniconfig==1.1.1
      - jinja2==3.0.3
      - markupsafe==2.0.1
      - packaging==21.3
      - pluggy==1.0.0
      - py==1.11.0
      - pyparsing==3.1.4
      - pytest==7.0.1
      - python-dateutil==2.9.0.post0
      - requests==2.27.1
      - requests-toolbelt==1.0.0
      - six==1.17.0
      - tomli==1.2.3
      - typing-extensions==4.1.1
      - urllib3==1.26.20
      - websocket-client==0.53.0
      - zipp==3.6.0
prefix: /opt/conda/envs/agavepy

tests/files_test.py::TestMockServer::test_files_import
tests/files_test.py::TestMockServer::test_files_download tests/files_test.py::TestMockServer::test_files_upload tests/files_test.py::TestMockServer::test_files_delete tests/files_test.py::TestMockServer::test_files_copy tests/files_test.py::TestMockServer::test_files_move tests/files_test.py::TestMockServer::test_files_mkdir
agavepy/files/__init__.py docs/docsite/files/files.rst agavepy/files/import_files.py agavepy/agave.py
agavepy/files/__init__.py docs/docsite/files/files.rst agavepy/files/import_files.py agavepy/agave.py