diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 0dadd63d7448cd4dbba193405741e0e816813966..6436dbaf1ef78f8b12633860b1a1c742680850f7 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -45,10 +45,13 @@ phutil_register_library_map(array(
     'SprintHistoryController' => 'controller/SprintHistoryController.php',
     'SprintHistoryDataProvider' => 'storage/SprintHistoryDataProvider.php',
     'SprintHistoryTableView' => 'view/reports/SprintHistoryTableView.php',
+    'SprintInfoConduitAPIMethod' => 'conduit/SprintInfoConduitAPIMethod.php',
     'SprintIsSprintField' => 'customfield/SprintIsSprintField.php',
     'SprintListController' => 'controller/SprintListController.php',
     'SprintListDataProvider' => 'storage/SprintListDataProvider.php',
     'SprintListTableView' => 'view/SprintListTableView.php',
+    'SprintManiphestConduitAPIMethod' => 'conduit/SprintManiphestConduitAPIMethod.php',
+    'SprintManiphestQueryConduitAPIMethod' => 'conduit/SprintManiphestQueryConduitAPIMethod.php',
     'SprintPoints' => 'util/SprintPoints.php',
     'SprintProjectController' => 'controller/SprintProjectController.php',
     'SprintProjectCustomField' => 'customfield/SprintProjectCustomField.php',
@@ -107,9 +110,12 @@ phutil_register_library_map(array(
     'SprintHandleIconView' => 'AphrontTagView',
     'SprintHistoryController' => 'SprintController',
     'SprintHistoryTableView' => 'SprintView',
+    'SprintInfoConduitAPIMethod' => 'SprintManiphestConduitAPIMethod',
     'SprintIsSprintField' => 'SprintProjectCustomField',
     'SprintListController' => 'SprintController',
     'SprintListTableView' => 'Phobject',
+    'SprintManiphestConduitAPIMethod' => 'ConduitAPIMethod',
+    'SprintManiphestQueryConduitAPIMethod' => 'SprintManiphestConduitAPIMethod',
     'SprintPoints' => 'Phobject',
     'SprintProjectController' => 'SprintController',
     'SprintProjectCustomField' => array(
diff --git a/src/conduit/SprintInfoConduitAPIMethod.php b/src/conduit/SprintInfoConduitAPIMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..3bc7cbffdd28887722f8c12530657e91f96b64c8
--- /dev/null
+++ b/src/conduit/SprintInfoConduitAPIMethod.php
@@ -0,0 +1,45 @@
+<?php
+
+final class SprintInfoConduitAPIMethod extends SprintManiphestConduitAPIMethod {
+
+  public function getAPIMethodName() {
+    return 'sprint.info';
+  }
+
+  public function getMethodDescription() {
+    return pht('Retrieve points and info for a Maniphest task, given its ID.');
+  }
+
+  protected function defineParamTypes() {
+    return array(
+        'task_id' => 'required id',
+    );
+  }
+
+  protected function defineReturnType() {
+    return 'nonempty dict';
+  }
+
+  protected function defineErrorTypes() {
+    return array(
+        'ERR_BAD_TASK' => pht('No such Maniphest task exists.'),
+    );
+  }
+
+  protected function execute(ConduitAPIRequest $request) {
+    $task_id = $request->getValue('task_id');
+
+    $task = id(new ManiphestTaskQuery())
+        ->setViewer($request->getUser())
+        ->withIDs(array($task_id))
+        ->needSubscriberPHIDs(true)
+        ->needProjectPHIDs(true)
+        ->executeOne();
+    if (!$task) {
+      throw new ConduitException('ERR_BAD_TASK');
+    }
+
+    return $this->buildTaskInfoDictionary($task);
+  }
+
+}
diff --git a/src/conduit/SprintManiphestConduitAPIMethod.php b/src/conduit/SprintManiphestConduitAPIMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..cbde1d8c926d7aed072f2aafc1147c15109eef56
--- /dev/null
+++ b/src/conduit/SprintManiphestConduitAPIMethod.php
@@ -0,0 +1,302 @@
+<?php
+
+abstract class SprintManiphestConduitAPIMethod extends ConduitAPIMethod {
+
+  final public function getApplication() {
+    return PhabricatorApplication::getByClass(
+        'PhabricatorManiphestApplication');
+  }
+
+  protected function defineErrorTypes() {
+    return array(
+        'ERR-INVALID-PARAMETER' => pht('Missing or malformed parameter.'),
+    );
+  }
+
+  protected function buildTaskInfoDictionary(ManiphestTask $task) {
+    $results = $this->buildTaskInfoDictionaries(array($task));
+    return idx($results, $task->getPHID());
+  }
+
+  protected function getTaskFields($is_new) {
+    $fields = array();
+
+    if (!$is_new) {
+      $fields += array(
+          'id'    => 'optional int',
+          'phid'  => 'optional int',
+      );
+    }
+
+    $fields += array(
+        'title'         => $is_new ? 'required string' : 'optional string',
+        'description'   => 'optional string',
+        'ownerPHID'     => 'optional phid',
+        'viewPolicy'    => 'optional phid or policy string',
+        'editPolicy'    => 'optional phid or policy string',
+        'ccPHIDs'       => 'optional list<phid>',
+        'priority'      => 'optional int',
+        'projectPHIDs'  => 'optional list<phid>',
+        'auxiliary'     => 'optional dict',
+        'points'        => 'optional int'
+    );
+
+    if (!$is_new) {
+      $fields += array(
+          'status'    => 'optional string',
+          'comments'  => 'optional string',
+      );
+    }
+
+    return $fields;
+  }
+
+  protected function applyRequest(
+      ManiphestTask $task,
+      ConduitAPIRequest $request,
+      $is_new) {
+
+    $changes = array();
+
+    if ($is_new) {
+      $task->setTitle((string)$request->getValue('title'));
+      $task->setDescription((string)$request->getValue('description'));
+      $changes[ManiphestTransaction::TYPE_STATUS] =
+          ManiphestTaskStatus::getDefaultStatus();
+      $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
+          array('+' => array($request->getUser()->getPHID()));
+    } else {
+
+      $comments = $request->getValue('comments');
+      if (!$is_new && $comments !== null) {
+        $changes[PhabricatorTransactions::TYPE_COMMENT] = null;
+      }
+
+      $title = $request->getValue('title');
+      if ($title !== null) {
+        $changes[ManiphestTransaction::TYPE_TITLE] = $title;
+      }
+
+      $desc = $request->getValue('description');
+      if ($desc !== null) {
+        $changes[ManiphestTransaction::TYPE_DESCRIPTION] = $desc;
+      }
+
+      $status = $request->getValue('status');
+      if ($status !== null) {
+        $valid_statuses = ManiphestTaskStatus::getTaskStatusMap();
+        if (!isset($valid_statuses[$status])) {
+          throw id(new ConduitException('ERR-INVALID-PARAMETER'))
+              ->setErrorDescription(pht('Status set to invalid value.'));
+        }
+        $changes[ManiphestTransaction::TYPE_STATUS] = $status;
+      }
+    }
+
+    $priority = $request->getValue('priority');
+    if ($priority !== null) {
+      $valid_priorities = ManiphestTaskPriority::getTaskPriorityMap();
+      if (!isset($valid_priorities[$priority])) {
+        throw id(new ConduitException('ERR-INVALID-PARAMETER'))
+            ->setErrorDescription(pht('Priority set to invalid value.'));
+      }
+      $changes[ManiphestTransaction::TYPE_PRIORITY] = $priority;
+    }
+
+    $owner_phid = $request->getValue('ownerPHID');
+    if ($owner_phid !== null) {
+      $this->validatePHIDList(
+          array($owner_phid),
+          PhabricatorPeopleUserPHIDType::TYPECONST,
+          'ownerPHID');
+      $changes[ManiphestTransaction::TYPE_OWNER] = $owner_phid;
+    }
+
+    $ccs = $request->getValue('ccPHIDs');
+    if ($ccs !== null) {
+      $changes[PhabricatorTransactions::TYPE_SUBSCRIBERS] =
+          array('=' => array_fuse($ccs));
+    }
+
+    $transactions = array();
+
+    $view_policy = $request->getValue('viewPolicy');
+    if ($view_policy !== null) {
+      $transactions[] = id(new ManiphestTransaction())
+          ->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
+          ->setNewValue($view_policy);
+    }
+
+    $edit_policy = $request->getValue('editPolicy');
+    if ($edit_policy !== null) {
+      $transactions[] = id(new ManiphestTransaction())
+          ->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
+          ->setNewValue($edit_policy);
+    }
+
+    $project_phids = $request->getValue('projectPHIDs');
+    if ($project_phids !== null) {
+      $this->validatePHIDList(
+          $project_phids,
+          PhabricatorProjectProjectPHIDType::TYPECONST,
+          'projectPHIDS');
+
+      $project_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
+      $transactions[] = id(new ManiphestTransaction())
+          ->setTransactionType(PhabricatorTransactions::TYPE_EDGE)
+          ->setMetadataValue('edge:type', $project_type)
+          ->setNewValue(
+              array(
+                  '=' => array_fuse($project_phids),
+              ));
+    }
+
+    $template = new ManiphestTransaction();
+
+    foreach ($changes as $type => $value) {
+      $transaction = clone $template;
+      $transaction->setTransactionType($type);
+      if ($type == PhabricatorTransactions::TYPE_COMMENT) {
+        $transaction->attachComment(
+            id(new ManiphestTransactionComment())
+                ->setContent($comments));
+      } else {
+        $transaction->setNewValue($value);
+      }
+
+      $transactions[] = $transaction;
+    }
+
+    $field_list = PhabricatorCustomField::getObjectFields(
+        $task,
+        PhabricatorCustomField::ROLE_EDIT);
+    $field_list->readFieldsFromStorage($task);
+
+    $auxiliary = $request->getValue('auxiliary');
+    if ($auxiliary) {
+      foreach ($field_list->getFields() as $key => $field) {
+        if (!array_key_exists($key, $auxiliary)) {
+          continue;
+        }
+        $transaction = clone $template;
+        $transaction->setTransactionType(
+            PhabricatorTransactions::TYPE_CUSTOMFIELD);
+        $transaction->setMetadataValue('customfield:key', $key);
+        $transaction->setOldValue(
+            $field->getOldValueForApplicationTransactions());
+        $transaction->setNewValue($auxiliary[$key]);
+        $transactions[] = $transaction;
+      }
+    }
+
+    if (!$transactions) {
+      return;
+    }
+
+    $content_source = PhabricatorContentSource::newForSource(
+        PhabricatorContentSource::SOURCE_CONDUIT,
+        array());
+
+    $editor = id(new ManiphestTransactionEditor())
+        ->setActor($request->getUser())
+        ->setContentSource($content_source)
+        ->setContinueOnNoEffect(true);
+
+    if (!$is_new) {
+      $editor->setContinueOnMissingFields(true);
+    }
+
+    $editor->applyTransactions($task, $transactions);
+
+    // reload the task now that we've done all the fun stuff
+    return id(new ManiphestTaskQuery())
+        ->setViewer($request->getUser())
+        ->withPHIDs(array($task->getPHID()))
+        ->needSubscriberPHIDs(true)
+        ->needProjectPHIDs(true)
+        ->executeOne();
+  }
+
+  protected function buildTaskInfoDictionaries(array $tasks) {
+    assert_instances_of($tasks, 'ManiphestTask');
+    if (!$tasks) {
+      return array();
+    }
+
+    $task_phids = mpull($tasks, 'getPHID');
+
+    $all_deps = id(new PhabricatorEdgeQuery())
+        ->withSourcePHIDs($task_phids)
+        ->withEdgeTypes(array(ManiphestTaskDependsOnTaskEdgeType::EDGECONST));
+    $all_deps->execute();
+
+    $result = array();
+    foreach ($tasks as $task) {
+      // TODO: Batch this get as CustomField gets cleaned up.
+      $field_list = PhabricatorCustomField::getObjectFields(
+          $task,
+          PhabricatorCustomField::ROLE_EDIT);
+      $field_list->readFieldsFromStorage($task);
+
+      $auxiliary = mpull(
+          $field_list->getFields(),
+          'getValueForStorage',
+          'getFieldKey');
+
+      $task_deps = $all_deps->getDestinationPHIDs(
+          array($task->getPHID()),
+          array(ManiphestTaskDependsOnTaskEdgeType::EDGECONST));
+
+      $result[$task->getPHID()] = array(
+          'id'           => $task->getID(),
+          'phid'         => $task->getPHID(),
+          'points'       => $task->getPoints(),
+          'authorPHID'   => $task->getAuthorPHID(),
+          'ownerPHID'    => $task->getOwnerPHID(),
+          'ccPHIDs'      => $task->getSubscriberPHIDs(),
+          'status'       => $task->getStatus(),
+          'statusName'   => ManiphestTaskStatus::getTaskStatusName(
+              $task->getStatus()),
+          'isClosed'     => $task->isClosed(),
+          'priority'     => ManiphestTaskPriority::getTaskPriorityName(
+              $task->getPriority()),
+          'priorityColor' => ManiphestTaskPriority::getTaskPriorityColor(
+              $task->getPriority()),
+          'title'        => $task->getTitle(),
+          'description'  => $task->getDescription(),
+          'projectPHIDs' => $task->getProjectPHIDs(),
+          'uri'          => PhabricatorEnv::getProductionURI('/T'.$task->getID()),
+          'auxiliary'    => $auxiliary,
+          'objectName'   => 'T'.$task->getID(),
+          'dateCreated'  => $task->getDateCreated(),
+          'dateModified' => $task->getDateModified(),
+          'dependsOnTaskPHIDs' => $task_deps,
+      );
+    }
+
+    return $result;
+  }
+
+  /**
+   * NOTE: This is a temporary stop gap since its easy to make malformed tasks.
+   * Long-term, the values set in @{method:defineParamTypes} will be used to
+   * validate data implicitly within the larger Conduit application.
+   *
+   * TODO: Remove this in favor of generalized Conduit hotness.
+   */
+  private function validatePHIDList(array $phid_list, $phid_type, $field) {
+    $phid_groups = phid_group_by_type($phid_list);
+    unset($phid_groups[$phid_type]);
+    if (!empty($phid_groups)) {
+      throw id(new ConduitException('ERR-INVALID-PARAMETER'))
+          ->setErrorDescription(
+              pht(
+                  'One or more PHIDs were invalid for %s.',
+                  $field));
+    }
+
+    return true;
+  }
+
+}
+
diff --git a/src/conduit/SprintManiphestQueryConduitAPIMethod.php b/src/conduit/SprintManiphestQueryConduitAPIMethod.php
new file mode 100644
index 0000000000000000000000000000000000000000..c5c737dd2551b286be4311a00e40782f3370f29f
--- /dev/null
+++ b/src/conduit/SprintManiphestQueryConduitAPIMethod.php
@@ -0,0 +1,122 @@
+<?php
+
+final class SprintManiphestQueryConduitAPIMethod extends SprintManiphestConduitAPIMethod {
+
+  public function getAPIMethodName() {
+    return 'sprint.query';
+  }
+
+  public function getMethodDescription() {
+    return pht('Execute complex searches for Maniphest tasks.');
+  }
+
+  protected function defineParamTypes() {
+    $statuses = array(
+        ManiphestTaskQuery::STATUS_ANY,
+        ManiphestTaskQuery::STATUS_OPEN,
+        ManiphestTaskQuery::STATUS_CLOSED,
+        ManiphestTaskQuery::STATUS_RESOLVED,
+        ManiphestTaskQuery::STATUS_WONTFIX,
+        ManiphestTaskQuery::STATUS_INVALID,
+        ManiphestTaskQuery::STATUS_SPITE,
+        ManiphestTaskQuery::STATUS_DUPLICATE,
+    );
+    $status_const = $this->formatStringConstants($statuses);
+
+    $orders = array(
+        ManiphestTaskQuery::ORDER_PRIORITY,
+        ManiphestTaskQuery::ORDER_CREATED,
+        ManiphestTaskQuery::ORDER_MODIFIED,
+    );
+    $order_const = $this->formatStringConstants($orders);
+
+    return array(
+        'ids'               => 'optional list<uint>',
+        'phids'             => 'optional list<phid>',
+        'ownerPHIDs'        => 'optional list<phid>',
+        'authorPHIDs'       => 'optional list<phid>',
+        'projectPHIDs'      => 'optional list<phid>',
+        'ccPHIDs'           => 'optional list<phid>',
+        'fullText'          => 'optional string',
+
+        'status'            => 'optional '.$status_const,
+        'order'             => 'optional '.$order_const,
+
+        'limit'             => 'optional int',
+        'offset'            => 'optional int',
+    );
+  }
+
+  protected function defineReturnType() {
+    return 'list';
+  }
+
+  protected function execute(ConduitAPIRequest $request) {
+    $query = id(new ManiphestTaskQuery())
+        ->setViewer($request->getUser())
+        ->needProjectPHIDs(true)
+        ->needSubscriberPHIDs(true);
+
+    $task_ids = $request->getValue('ids');
+    if ($task_ids) {
+      $query->withIDs($task_ids);
+    }
+
+    $task_phids = $request->getValue('phids');
+    if ($task_phids) {
+      $query->withPHIDs($task_phids);
+    }
+
+    $owners = $request->getValue('ownerPHIDs');
+    if ($owners) {
+      $query->withOwners($owners);
+    }
+
+    $authors = $request->getValue('authorPHIDs');
+    if ($authors) {
+      $query->withAuthors($authors);
+    }
+
+    $projects = $request->getValue('projectPHIDs');
+    if ($projects) {
+      $query->withEdgeLogicPHIDs(
+          PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
+          PhabricatorQueryConstraint::OPERATOR_AND,
+          $projects);
+    }
+
+    $ccs = $request->getValue('ccPHIDs');
+    if ($ccs) {
+      $query->withSubscribers($ccs);
+    }
+
+    $full_text = $request->getValue('fullText');
+    if ($full_text) {
+      $query->withFullTextSearch($full_text);
+    }
+
+    $status = $request->getValue('status');
+    if ($status) {
+      $query->withStatus($status);
+    }
+
+    $order = $request->getValue('order');
+    if ($order) {
+      $query->setOrder($order);
+    }
+
+    $limit = $request->getValue('limit');
+    if ($limit) {
+      $query->setLimit($limit);
+    }
+
+    $offset = $request->getValue('offset');
+    if ($offset) {
+      $query->setOffset($offset);
+    }
+
+    $results = $query->execute();
+    return $this->buildTaskInfoDictionaries($results);
+  }
+
+}