diff --git a/src/metabase/api/dataset.clj b/src/metabase/api/dataset.clj
index 0504ee587e03bd18bb53f53383cf9577d7c325b4..b1357fa8faa6944f1dfc7f11045612db50df1bf1 100644
--- a/src/metabase/api/dataset.clj
+++ b/src/metabase/api/dataset.clj
@@ -3,9 +3,12 @@
   (:require [clojure.data.csv :as csv]
             [compojure.core :refer [GET POST]]
             [metabase.api.common :refer :all]
+            [metabase.db :as db]
             [metabase.driver :as driver]
             [metabase.driver.query-processor :refer [structured-query?]]
+            [metabase.models.card :refer [Card]]
             [metabase.models.database :refer [Database]]
+            [metabase.models.hydrate :refer [hydrate]]
             [metabase.util :as u]))
 
 (def ^:const api-max-results-bare-rows
@@ -16,14 +19,17 @@
   "General maximum number of rows to return from an API query."
   10000)
 
+(def ^:const dataset-query-api-constraints
+  "Default map of constraints that we apply on dataset queries executed by the api."
+  {:max-results           api-max-results
+   :max-results-bare-rows api-max-results-bare-rows})
 
 (defendpoint POST "/"
   "Execute an MQL query and retrieve the results as JSON."
   [:as {{:keys [database] :as body} :body}]
   (read-check Database database)
   ;; add sensible constraints for results limits on our query
-  (let [query (assoc body :constraints {:max-results           api-max-results
-                                        :max-results-bare-rows api-max-results-bare-rows})]
+  (let [query (assoc body :constraints dataset-query-api-constraints)]
     (driver/dataset-query query {:executed_by *current-user-id*})))
 
 
@@ -45,4 +51,19 @@
       {:status 500
        :body   (:error response)})))
 
+(defendpoint GET "/card/:id"
+  "Execute the MQL query for a given `Card` and retrieve both the `Card` and the execution results as JSON.
+   This is a convenience endpoint which simplifies the normal 2 api calls to fetch the `Card` then execute its query."
+  [id]
+  (let-404 [{:keys [dataset_query] :as card} (db/sel :one Card :id id)]
+    (read-check card)
+    (read-check Database (:database dataset_query))
+    ;; add sensible constraints for results limits on our query
+    ;; TODO: it would be nice to associate the card :id with the query execution tracking
+    (let [query   (assoc dataset_query :constraints dataset-query-api-constraints)
+          options {:executed_by *current-user-id*}]
+      {:card   (hydrate card :creator)
+       :result (driver/dataset-query query options)})))
+
+
 (define-routes)
diff --git a/src/metabase/driver.clj b/src/metabase/driver.clj
index d81dfe2234547a246c9859eb35e4aed24f08ebea..ac625ad8bd1db56fede7fad29c79ea101d3356ff 100644
--- a/src/metabase/driver.clj
+++ b/src/metabase/driver.clj
@@ -441,6 +441,7 @@
         (dissoc :start_time_millis)
         (merge updates)
         (save-query-execution)
+        (dissoc :raw_query :result_rows :version)
         ;; this is just for the response for clien
         (assoc :error     error-message
                :row_count 0
@@ -460,7 +461,7 @@
       (dissoc :start_time_millis)
       (save-query-execution)
       ;; at this point we've saved and we just need to massage things into our final response format
-      (select-keys [:id :uuid])
+      (dissoc :error :raw_query :result_rows :version)
       (merge query-result)))
 
 (defn save-query-execution
diff --git a/test/metabase/api/dataset_test.clj b/test/metabase/api/dataset_test.clj
index b91f6635fcd489fe12d2d270c302c7f73ff68b53..06d810ca8fe2fc51a0008c75d5310e5019a6bfb6 100644
--- a/test/metabase/api/dataset_test.clj
+++ b/test/metabase/api/dataset_test.clj
@@ -1,48 +1,186 @@
 (ns metabase.api.dataset-test
   "Unit tests for /api/dataset endpoints."
   (:require [expectations :refer :all]
-            [korma.core :as k]
+            [metabase.api.dataset :refer [dataset-query-api-constraints]]
             [metabase.db :refer :all]
             [metabase.driver.query-processor.expand :as ql]
+            [metabase.models.card :refer [Card]]
             [metabase.models.query-execution :refer [QueryExecution]]
-            [metabase.test.data :refer :all]
             [metabase.test.data.users :refer :all]
-            [metabase.test.util :refer [match-$ expect-eval-actual-first]]))
+            [metabase.test.data :refer :all]
+            [metabase.test.util :as tu]))
+
+
+(defn user-details [user]
+  (tu/match-$ user
+              {:email $
+               :date_joined $
+               :first_name $
+               :last_name $
+               :last_login $
+               :is_superuser $
+               :common_name $}))
+
+(defn remove-ids-and-boolean-timestamps [m]
+  (let [f (fn [v]
+            (cond
+              (map? v) (remove-ids-and-boolean-timestamps v)
+              (coll? v) (mapv remove-ids-and-boolean-timestamps v)
+              :else v))]
+    (into {} (for [[k v] m]
+               (when-not (or (= :id k)
+                             (.endsWith (name k) "_id"))
+                 (if (or (= :created_at k)
+                         (= :updated_at k))
+                   [k (not (nil? v))]
+                   [k (f v)]))))))
+
+(defn format-response [m]
+  (into {} (for [[k v] m]
+             (if (contains? #{:id :uuid :started_at :finished_at :running_time} k)
+               [k (boolean v)]
+               [k v]))))
 
 ;;; ## POST /api/meta/dataset
 ;; Just a basic sanity check to make sure Query Processor endpoint is still working correctly.
-(expect-eval-actual-first
-    (match-$ (sel :one :fields [QueryExecution :id :uuid] (k/order :id :desc))
-      {:data      {:rows    [[1000]]
+(expect
+  ;; the first result is directly from the api call
+  ;; the second result is checking our QueryExection log to ensure it captured the right details
+  [{:data         {:rows    [[1000]]
                    :columns ["count"]
                    :cols    [{:base_type "IntegerField", :special_type "number", :name "count", :display_name "count", :id nil, :table_id nil,
                               :description nil, :target nil, :extra_info {}}]}
-       :row_count 1
-       :status    "completed"
-       :id        $
-       :uuid      $})
-  ((user->client :rasta) :post 200 "dataset" (ql/wrap-inner-query
-                                               (query checkins
-                                                 (ql/aggregation (ql/count))))))
+    :row_count    1
+    :status       "completed"
+    :id           true
+    :uuid         true
+    :json_query   (-> (ql/wrap-inner-query
+                        (query checkins
+                               (ql/aggregation (ql/count))))
+                      (assoc :type "query")
+                      (assoc-in [:query :aggregation] {:aggregation-type "count"})
+                      (assoc :constraints dataset-query-api-constraints))
+    :started_at   true
+    :finished_at  true
+    :running_time true}
+   {:row_count    1
+    :result_rows  1
+    :status       :completed
+    :error        ""
+    :id           true
+    :uuid         true
+    :raw_query    ""
+    :json_query   (-> (ql/wrap-inner-query
+                        (query checkins
+                               (ql/aggregation (ql/count))))
+                      (assoc :type "query")
+                      (assoc-in [:query :aggregation] {:aggregation-type "count"})
+                      (assoc :constraints dataset-query-api-constraints))
+    :started_at   true
+    :finished_at  true
+    :running_time true
+    :version      0}]
+  (let [result ((user->client :rasta) :post 200 "dataset" (ql/wrap-inner-query
+                                                            (query checkins
+                                                                   (ql/aggregation (ql/count)))))]
+    [(format-response result)
+     (format-response (sel :one QueryExecution :uuid (:uuid result)))]))
 
 ;; Even if a query fails we still expect a 200 response from the api
-(expect-eval-actual-first
-    (match-$ (sel :one QueryExecution (k/order :id :desc))
-      {:data         {:rows    []
-                      :cols    []
-                      :columns []}
-       :error        "Syntax error in SQL statement \"FOOBAR[*] \"; expected \"FROM, {\""
-       :raw_query    ""
-       :row_count    0
-       :result_rows  0
-       :status       "failed"
-       :version      0
-       :json_query   $
-       :started_at   $
-       :finished_at  $
-       :running_time $
-       :id           $
-       :uuid         $})
-    ((user->client :rasta) :post 200 "dataset" {:database (id)
-                                                :type     "native"
-                                                :native   {:query "foobar"}}))
+(expect
+  ;; the first result is directly from the api call
+  ;; the second result is checking our QueryExection log to ensure it captured the right details
+  (let [output {:data         {:rows    []
+                               :columns []
+                               :cols    []}
+                :row_count    0
+                :status       "failed"
+                :error        "Syntax error in SQL statement \"FOOBAR[*] \"; expected \"FROM, {\""
+                :id           true
+                :uuid         true
+                :json_query   {:database    (id)
+                               :type        "native"
+                               :native      {:query "foobar"}
+                               :constraints dataset-query-api-constraints}
+                :started_at   true
+                :finished_at  true
+                :running_time true}]
+    [output
+     (-> output
+         (dissoc :data)
+         (assoc :status      :failed
+                :version     0
+                :raw_query   ""
+                :result_rows 0))])
+  (let [result ((user->client :rasta) :post 200 "dataset" {:database (id)
+                                                           :type     "native"
+                                                           :native   {:query "foobar"}})]
+    [(format-response result)
+     (format-response (sel :one QueryExecution :uuid (:uuid result)))]))
+
+
+;; GET /api/dataset/card/:id
+(expect
+  ;; the first result is directly from the api call
+  ;; the second result is checking our QueryExection log to ensure it captured the right details
+  [{:card   {:name                   "Dataset Test Card"
+             :description            nil
+             :public_perms           0
+             :creator                (user-details (fetch-user :rasta))
+             :display                "scalar"
+             :query_type             "query"
+             :dataset_query          (-> (ql/wrap-inner-query
+                                           (query checkins
+                                                  (ql/aggregation (ql/count))))
+                                         (assoc :type "query")
+                                         (assoc-in [:query :aggregation] {:aggregation-type "count"}))
+             :visualization_settings {}
+             :created_at             true
+             :updated_at             true}
+    :result {:data         {:rows    [[1000]]
+                            :columns ["count"]
+                            :cols    [{:base_type "IntegerField", :special_type "number", :name "count", :display_name "count", :id nil, :table_id nil,
+                                       :description nil, :target nil, :extra_info {}}]}
+             :row_count    1
+             :status       "completed"
+             :id           true
+             :uuid         true
+             :json_query   (-> (ql/wrap-inner-query
+                                 (query checkins
+                                        (ql/aggregation (ql/count))))
+                               (assoc :type "query")
+                               (assoc-in [:query :aggregation] {:aggregation-type "count"})
+                               (assoc :constraints dataset-query-api-constraints))
+             :started_at   true
+             :finished_at  true
+             :running_time true}}
+   {:row_count    1
+    :result_rows  1
+    :status       :completed
+    :error        ""
+    :id           true
+    :uuid         true
+    :raw_query    ""
+    :json_query   (-> (ql/wrap-inner-query
+                        (query checkins
+                               (ql/aggregation (ql/count))))
+                      (assoc :type "query")
+                      (assoc-in [:query :aggregation] {:aggregation-type "count"})
+                      (assoc :constraints dataset-query-api-constraints))
+    :started_at   true
+    :finished_at  true
+    :running_time true
+    :version      0}]
+  (tu/with-temp Card [{card-id :id} {:name                   "Dataset Test Card"
+                                     :creator_id             (user->id :rasta)
+                                     :public_perms           0
+                                     :display                "scalar"
+                                     :dataset_query          (ql/wrap-inner-query
+                                                               (query checkins
+                                                                      (ql/aggregation (ql/count))))
+                                     :visualization_settings {}}]
+    (let [result ((user->client :rasta) :get 200 (format "dataset/card/%d" card-id))]
+      [(-> result
+           (update :card remove-ids-and-boolean-timestamps)
+           (update :result format-response))
+       (format-response (sel :one QueryExecution :uuid (get-in result [:result :uuid])))])))