Index: includes/api/ApiQuerySearch.php
===================================================================
--- includes/api/ApiQuerySearch.php	(revision 69201)
+++ includes/api/ApiQuerySearch.php	(working copy)
@@ -73,6 +73,9 @@
 			$matches = $search->searchText( $query );
 		} elseif ( $what == 'title' ) {
 			$matches = $search->searchTitle( $query );
+		} elseif ( $what == 'nearmatch' ) {
+			$query = str_replace( '_', ' ', $query );
+			$matches = SearchEngine::getNearMatchResultSet( $query );
 		} else {
 			// We default to title searches; this is a terrible legacy
 			// of the way we initially set up the MySQL fulltext-based
@@ -175,6 +178,7 @@
 				ApiBase::PARAM_TYPE => array(
 					'title',
 					'text',
+					'nearmatch',
 				)
 			),
 			'info' => array(
Index: includes/search/SearchEngine.php
===================================================================
--- includes/search/SearchEngine.php	(revision 69201)
+++ includes/search/SearchEngine.php	(working copy)
@@ -83,6 +83,17 @@
 		wfRunHooks( 'SearchGetNearMatchComplete', array( $searchterm, &$title ) );
 		return $title;
 	}
+	
+	/**
+	 * Do a near match (see SearchEngine::getNearMatch) and wrap it into a 
+	 * SearchResultSet.
+	 * 
+	 * @param $searchterm string
+	 * @return SearchResultSet
+	 */
+	public static function getNearMatchResultSet( $searchterm ) {
+		return new SearchNearMatchResultSet( self::getNearMatch( $searchterm ) );
+	}
 
 	/**
 	 * Really find the title match.
@@ -573,7 +584,9 @@
 		$row = $this->mResultSet->fetchObject();
 		if ($row === false)
 			return false;
-		return new SearchResult($row);
+			
+		$title = Title::makeTitle( $row->page_namespace, $row->page_title );
+		return new SearchResult( $title );
 	}
 
 	function free() {
@@ -602,8 +615,14 @@
 	var $mRevision = null;
 	var $mImage = null;
 
-	function __construct( $row ) {
-		$this->mTitle = Title::makeTitle( $row->page_namespace, $row->page_title );
+	
+	function __construct( $title ) {
+		if ( $title instanceof Title ) {
+			$this->mTitle = $title;
+		} else {
+			// Backwards compatibility with pre-1.17 callers
+			$this->mTitle = Title::makeTitle( $title->page_namespace, $title->page_title );
+		}
 		if( !is_null($this->mTitle) ){
 			$this->mRevision = Revision::newFromTitle( $this->mTitle );
 			if( $this->mTitle->getNamespace() === NS_FILE )
@@ -751,6 +770,31 @@
 		return '';
 	}
 }
+/**
+ * A SearchResultSet wrapper for SearchEngine::getNearMatch
+ */
+class SearchNearMatchResultSet extends SearchResultSet {
+	private $fetched = false;
+	/**
+	 * @param $match mixed Title if matched, else null
+	 */
+	public function __construct( $match ) {
+		$this->result = $match;
+	}
+	public function hasResult() {
+		return (bool)$this->result;
+	}
+	public function numRows() {
+		return $this->hasResults() ? 1 : 0;
+	}
+	public function next() {
+		if ( $this->fetched || !$this->result ) {
+			return false;
+		}
+		$this->fetched = true;
+		return new SearchResult( $this->result );
+	}
+}
 
 /**
  * Highlight bits of wikitext
