diff --git a/config/ci_test.yaml.example b/config/ci_test.yaml.example
index 178999eab5bfbc82269149dc6b3e3b946e7b0489..135d40ef37ffa28711025b9ab4bb135381094664 100644
--- a/config/ci_test.yaml.example
+++ b/config/ci_test.yaml.example
@@ -211,3 +211,26 @@ dimensions:
         parent: "dim:0"
         relation: "year"
         description: "A dimension of Blendb. Has 1 possible value."
+enumTypes:
+    -
+        name: "enum type:0"
+        values:
+        - "test:0"
+        - "test:1"
+        - "test:2"
+        - "test:3"
+    -
+        name: "enum type:1"
+        values:
+        - "test:4"
+        - "test:5"
+        - "test:6"        
+    -
+        name: "enum type:2"
+        values:
+        - "test:7"
+        - "test:8"
+    -
+        name: "enum type:3"
+        values:
+        - "test:9"        
diff --git a/specs/blendb-api-v1.raml b/specs/blendb-api-v1.raml
index 2693c9cae169ea0dbc0c6d65322bc9d88f869b71..a8ca0cba4b0f2bb688a46f2a2bf7cb52a5273d32 100644
--- a/specs/blendb-api-v1.raml
+++ b/specs/blendb-api-v1.raml
@@ -287,7 +287,13 @@ traits:
         the system and their descriptions.
     securedBy: [ null, oauth_2_0 ]
     get:
-
+/enumtypes:
+    description: |
+        A EnumType is short for enumerable type. This is a special data type that only accepts a few possible values. This
+        collection allows the user to list all the enumerable types available in the system, their descriptions and possible
+        values.
+    get:    
+    securedBy: [ null, oauth_2_0 ]    
 /data:
     description: |
       This is the main part of the API. You may query it for report
diff --git a/src/adapter/sql.ts b/src/adapter/sql.ts
index 244863a3d75ed938e69d3250402bcdb4347fdb41..3600c1b81b0184357d88f5f723fd92fd61149aed 100644
--- a/src/adapter/sql.ts
+++ b/src/adapter/sql.ts
@@ -199,7 +199,7 @@ export abstract class SQLAdapter extends Adapter {
                         materialized: false
                     });
                     const from  = "(" +
-                                   this.buildQuery(partial, [partialJoin[i]]) +
+                                   this.buildQuery(partial, [partialJoin[i]], false) +
                                    ") AS view_" + partial.id + "\n";
 
                     partialJoin[i].id = partial.id;
@@ -302,7 +302,7 @@ export abstract class SQLAdapter extends Adapter {
                             materialized: false
                         });
                         const viewFrom  = "(" +
-                                    this.buildQuery(partial, segment[i]) +
+                                    this.buildQuery(partial, segment[i], false) +
                                     ") AS view_" + partial.id + "\n";
 
                         partialJoin.push({
@@ -507,7 +507,7 @@ export abstract class SQLAdapter extends Adapter {
                         materialized: false
                     }).id;
                     const viewFrom  = "(" +
-                            this.buildQuery(partial, [partial0, partial1]) +
+                            this.buildQuery(partial, [partial0, partial1], false) +
                             ") AS view_" + id + "\n";
                     partialJoin.push({
                         id: id,
@@ -532,7 +532,7 @@ export abstract class SQLAdapter extends Adapter {
             layer to the query, that is in fact unnecessary.
             Think a way to remove-it.
         */
-        return this.buildQuery(view, partialJoin) + ";";
+        return this.buildQuery(view, partialJoin, true) + ";";
     }
 
     private searchMaterializedViews(view: View): View[] {
@@ -551,10 +551,11 @@ export abstract class SQLAdapter extends Adapter {
         return r;
     }
 
-    private buildQuery(target: View, views: ExpandedView[]) {
+    private buildQuery(target: View, views: ExpandedView[], toSort: boolean) {
         const metrics = target.metrics;
         const dimensions = target.dimensions;
         const clauses = target.clauses;
+        const sort = target.sort;
 
         let dimMap: {[key: string]: DimInfo} = {};
         let nameMap: {[key: string]: ExpandedView} = {};
@@ -655,6 +656,11 @@ export abstract class SQLAdapter extends Adapter {
             }
         });
 
+        // Sorting
+        const order = sort.map((item) => {
+            return "\"" + item.name + "\"";
+        }).join(",");
+
         // Assembly
 
         const projection = "SELECT " + elements.join(",");
@@ -664,8 +670,9 @@ export abstract class SQLAdapter extends Adapter {
         if (grouped.length > 0) {
             grouping = " GROUP BY " + grouped.join(",");
         }
+        const sorting = (toSort && sort.length > 0) ? " ORDER BY " + order : "";
 
-        return projection + source + selection + grouping;
+        return projection + source + selection + grouping + sorting;
 
     }
 
diff --git a/src/api/controllers/data.spec.ts b/src/api/controllers/data.spec.ts
index 5cf78079cdf2b0e85ef8479b6b69e12dca38416f..4719012ee537f87792ecde6a13cf1e39296d4c56 100644
--- a/src/api/controllers/data.spec.ts
+++ b/src/api/controllers/data.spec.ts
@@ -29,6 +29,7 @@ interface StrQuery {
     metrics: string;
     dimensions: string;
     filters?: string;
+    sort?: string;
 }
 
 function parseQuery(obj: Query): StrQuery {
@@ -80,6 +81,27 @@ describe("API data controller", () => {
             .end(done);
     });
 
+    it("should respond 500 when query has sort item that is not in query data", (done) => {
+        let query = parseQuery(tests.clausal);
+        query.sort = "dim:0";
+        request(server)
+            .get("/v1/data")
+            .query(query)
+            .expect(500)
+            .expect((res: any) => {
+                const message = "Query execution failed: " +
+                "Could not construct query with the paramters given.";
+                const error = "The item 'dim:0'" +
+                    " is not present in neither metrics nor dimensions list";
+                expect(res.body).to.be.an("object");
+                expect(res.body).to.have.property("message");
+                expect(res.body).to.have.property("error");
+                expect(res.body.message).to.be.eql(message);
+                expect(res.body.error).to.be.eql(error);
+            })
+            .end(done);
+    });
+
     it("should respond 200 and get some data", (done) => {
         request(server)
             .get("/v1/data")
@@ -176,4 +198,31 @@ describe("API data controller", () => {
             .end(done);
     });
 
+    it("should respond 200 and get some data, sorted", (done) => {
+        // Clause does not come to scenario besause is a lot of work for
+        // only a single test
+        let query = parseQuery(tests.clausal);
+        query.sort = "dim:7,met:0";
+        request(server)
+            .get("/v1/data")
+            .query(query)
+            .expect(200)
+            .expect((res: any) => {
+                let result = res.body;
+                expect(result).to.be.an("array");
+                expect(result).to.have.length(5);
+                expect(result[0]).to.be.an("object");
+                let keys: string[] = [];
+                keys = keys.concat(tests.clausal.metrics.map((item) => item.name));
+                keys = keys.concat(tests.clausal.dimensions.map((item) => item.name));
+                for (let i = 0; i < result.length; ++i) {
+                    const row = result[i];
+                    expect(row).to.be.an("object");
+                    expect(row).to.have.all.keys(keys);
+                    expect(row["dim:7"]).to.be.eql(i + 1);
+                }
+            })
+            .end(done);
+    });
+
 });
diff --git a/src/api/controllers/data.ts b/src/api/controllers/data.ts
index 154adb99ae9e1df2f838d0c5e798632eb41970c9..add1317f681f8701b1b5b3991a2cd6c883342119 100644
--- a/src/api/controllers/data.ts
+++ b/src/api/controllers/data.ts
@@ -27,13 +27,17 @@ export class DataCtrl {
         let metrics = req.query.metrics.split(",").filter((item: string) => item !== "");
         let dimensions = req.query.dimensions.split(",").filter((item: string) => item !== "");
         let clauses = [];
+        let sort: string[] = [];
         if (req.query.filters) {
             clauses = req.query.filters.split(";").filter((item: string) => item !== "");
         }
+        if (req.query.sort) {
+            sort = req.query.sort.split(",").filter((item: string) => item !== "");
+        }
         let view;
 
         try {
-            let query: Query = { metrics: [], dimensions: [], clauses: [] };
+            let query: Query = { metrics: [], dimensions: [], clauses: [], sort: [] };
             for (let i = 0; i < metrics.length; ++i) {
                 query.metrics.push(req.engine.getMetricByName(metrics[i]));
             }
@@ -45,6 +49,26 @@ export class DataCtrl {
             for (let i = 0; i < clauses.length; ++i) {
                 query.clauses.push(req.engine.parseClause(clauses[i]));
             }
+
+            for (let i = 0; i < sort.length; ++i) {
+                const m = query.metrics.find((item) => item.name === sort[i]);
+                if (!m) {
+                    const d = query.dimensions.find((item) => item.name === sort[i]);
+                    if (!d) {
+                        throw new Error(
+                            "The item '" +  sort[i] +
+                            "' is not present in neither metrics nor dimensions list");
+                    }
+                    else {
+                        query.sort.push(d);
+                    }
+                }
+
+                else {
+                    query.sort.push(m);
+                }
+
+            }
             view = req.engine.query(query);
         }
         catch (e) {
diff --git a/src/api/controllers/engine.spec.ts b/src/api/controllers/engine.spec.ts
index 0d1ea0804b331b7c11197cc826df18bb32687410..3151989c3277c95d289931edc66335e5e94f7f80 100644
--- a/src/api/controllers/engine.spec.ts
+++ b/src/api/controllers/engine.spec.ts
@@ -48,5 +48,15 @@ describe("API engine controller", () => {
             })
             .end(done);
     });
+    it("should respond 200 and the list of enumTypes", (done) => {
+        request(server)
+            .get("/v1/enumtypes")
+            .expect((res: any) => {
+                let result = res.body;
+                expect(result).to.be.an("array");
+                expect(result).to.have.length(4);
+            })
+            .end(done);
+    });
 
 });
diff --git a/src/api/controllers/engine.ts b/src/api/controllers/engine.ts
index 18de1e1a4252ecfed38bf340af6fe67a21b2f6fe..874e7513bd602449c21fdcdb87d84a3ecf7644d6 100644
--- a/src/api/controllers/engine.ts
+++ b/src/api/controllers/engine.ts
@@ -29,4 +29,8 @@ export class EngineCtrl {
    public static dimensions(req: Request, res: express.Response, next: express.NextFunction) {
         res.status(200).json(req.engine.getDimensionsDescription());
     }
+
+    public static enumTypes(req: Request, res: express.Response, next: express.NextFunction) {
+        res.status(200).json(req.engine.getEnumTypesDescription());
+    }
 }
diff --git a/src/api/middlewares/engine.ts b/src/api/middlewares/engine.ts
index 8d1f764ea508530ce7f80e287add83de759bb97b..e01638997ca4898626ecc727886c2db3bda7388f 100644
--- a/src/api/middlewares/engine.ts
+++ b/src/api/middlewares/engine.ts
@@ -28,6 +28,7 @@ export function EngineMw (config: ParsedConfig): Middleware {
     config.metrics.forEach ((met) => engine.addMetric(met));
     config.dimensions.forEach ((dim) => engine.addDimension(dim));
     config.views.forEach ((view) => engine.addView(view));
+    config.enumTypes.forEach ((enumt) => engine.addEnumType(enumt));
 
     return function engineMiddleware(req, res, next) {
         req.engine = engine;
diff --git a/src/api/router-v1.ts b/src/api/router-v1.ts
index 53f3c05cf4998c2fa4fc90a30cee43fbef87b7b8..88073edc4292246914ab829a0f404099c5ecb1da 100644
--- a/src/api/router-v1.ts
+++ b/src/api/router-v1.ts
@@ -29,5 +29,6 @@ export const router = osprey.Router();
 
 router.get("/metrics", EngineCtrl.metrics);
 router.get("/dimensions", EngineCtrl.dimensions);
+router.get("/enumtypes", EngineCtrl.enumTypes);
 router.get("/data", DataCtrl.read);
 router.post("/collect/{class}", CollectCtrl.write);
diff --git a/src/common/query.ts b/src/common/query.ts
index dcbcb1f24cbec0d4ef85b45859facf519f85c4f8..fd7f646e012dbd213a65fe5c0949e79fa83827b6 100644
--- a/src/common/query.ts
+++ b/src/common/query.ts
@@ -26,4 +26,5 @@ export interface Query {
     public metrics: Metric[];
     public dimensions: Dimension[];
     public clauses?: Clause[];
+    public sort?: (Metric|Dimension)[];
 }
diff --git a/src/core/engine.ts b/src/core/engine.ts
index e1d842cfa473d950ed185a33b934bdb9600e911c..c18c96b2ae2a66137586d9e53c67d8c750508c2f 100644
--- a/src/core/engine.ts
+++ b/src/core/engine.ts
@@ -25,14 +25,17 @@ import { Filter } from "./filter";
 import { View } from "./view";
 import { Query } from "../common/query";
 import { Graph } from "../util/graph";
+import { EnumType, EnumTypeOptions} from "./enumType";
 
 export class Engine {
     private views: View[] = [];
     private metrics: Metric[] = [];
+    private enumTypes: EnumType[] = [];
     private dimensions: Dimension[] = [];
     private graph: Graph;
 
     constructor () {
+        this.enumTypes = [];
         this.views = [];
         this.metrics = [];
         this.dimensions = [];
@@ -47,6 +50,10 @@ export class Engine {
        return this.metrics.map((i) => i.strOptions());
     }
 
+    public getEnumTypesDescription(): EnumTypeOptions[] {
+        return this.enumTypes.map((i) => i.strOptions());
+    }
+
     public getDimensionsDescription() {
        return this.dimensions.map((i) => i.strOptions());
     }
@@ -60,6 +67,11 @@ export class Engine {
         return null;
     }
 
+    public addEnumType(enumType: EnumType) {
+        this.enumTypes.push(enumType);
+        return enumType;
+    }
+
     public addMetric(metric: Metric) {
         if (this.graph.addMetric(metric)) {
             this.metrics.push(metric);
@@ -163,13 +175,16 @@ export class Engine {
         const metrics =  q.metrics;
         const dimensions =  q.dimensions;
         const clauses =  ((q.clauses) ? q.clauses : []);
+        const sort =  ((q.sort) ? q.sort : []);
         if (optimalViews.length === 1 &&
             optimalViews[0].metrics.length === metrics.length &&
             optimalViews[0].dimensions.length === dimensions.length &&
             optimalViews[0].clauses.length === clauses.length &&
+            optimalViews[0].sort.length === sort.length &&
             optimalViews[0].metrics.every((item) => metrics.indexOf(item) !== -1) &&
             optimalViews[0].dimensions.every((item) => dimensions.indexOf(item) !== -1) &&
-            perfectMatch(optimalViews[0].clauses, clauses)) {
+            perfectMatch(optimalViews[0].clauses, clauses) &&
+            perfectOrder(optimalViews[0].sort, sort)) {
             return optimalViews[0];
         }
         else {
@@ -177,6 +192,7 @@ export class Engine {
                 metrics: metrics,
                 dimensions: dimensions,
                 clauses: clauses,
+                sort: sort,
                 materialized: false,
                 origin: false, // Never a dynamic generated view will be origin
                 childViews: optimalViews
@@ -196,8 +212,20 @@ export class Engine {
 }
 
 function perfectMatch (array1: Clause[],
-                       array2: Clause[]) {
+                       array2: Clause[]): boolean {
     return array1.every((item: Clause) => {
         return array2.some((otherItem: Clause) => item.id === otherItem.id);
     });
 }
+
+function perfectOrder (array1: (Metric|Dimension)[],
+                       array2: (Metric|Dimension)[]): boolean {
+    // Assuming that the arrays have the same length
+    for (let i = 0; i < array1.length; ++i) {
+        if (array1[i].name !== array2[i].name) {
+            return false;
+        }
+    }
+
+    return true;
+}
diff --git a/src/core/enumType.ts b/src/core/enumType.ts
new file mode 100644
index 0000000000000000000000000000000000000000..039b8b4a07921c85b4bc2cefa042eb8484bd271e
--- /dev/null
+++ b/src/core/enumType.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 Centro de Computacao Cientifica e Software Livre
+ * Departamento de Informatica - Universidade Federal do Parana
+ *
+ * This file is part of blend.
+ *
+ * blend 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.
+ *
+ * blend 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 blend.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+export interface EnumTypeOptions {
+    name: string;
+    values: string[];
+}
+export class EnumType {
+    public name: string;
+    public values: string[];
+
+    constructor(options: EnumTypeOptions) {
+        this.name = options.name;
+        this.values = options.values;
+    }
+    public strOptions(): EnumTypeOptions {
+        return{
+            name: this.name,
+            values: this.values
+        };
+    }
+}
diff --git a/src/core/view.ts b/src/core/view.ts
index 7634a8fe8e8548c520286a7185b37ead7f7a8942..29e6a63551e02ccfa64ffe858b2203815a72c7a9 100644
--- a/src/core/view.ts
+++ b/src/core/view.ts
@@ -34,6 +34,7 @@ export interface ViewOptions {
     keys?: Dimension[];
     origin: boolean;
     clauses?: Clause[];
+    sort?: (Metric|Dimension)[];
     materialized?: boolean;
     childViews?: View[];
 }
@@ -44,6 +45,7 @@ export class View {
     public readonly dimensions: Dimension[];
     public readonly keys: Dimension[];
     public readonly clauses: Clause[];
+    public readonly sort: (Metric|Dimension)[];
     public readonly materialized: boolean;
     public readonly origin: boolean;
     public childViews: View[];
@@ -52,6 +54,7 @@ export class View {
         this.metrics = options.metrics.sort();
         this.dimensions = options.dimensions.sort();
         this.clauses = (options.clauses) ? options.clauses.sort() : [];
+        this.sort = (options.sort) ? options.sort : [];
         this.materialized = options.materialized || false;
         this.origin = options.origin || false;
         this.childViews = (options.childViews) ? options.childViews : [];
diff --git a/src/util/configParser.ts b/src/util/configParser.ts
index c4abac077eff6b79594ef40d19f723f9be037756..af4c0a9fb9d8fde92675ef0032ea805d7e9b2a3c 100644
--- a/src/util/configParser.ts
+++ b/src/util/configParser.ts
@@ -21,6 +21,7 @@
 import { Metric, MetricOptions, MetricStrOptions } from "../core/metric";
 import { Dimension, DimensionOptions, DimensionStrOptions } from "../core/dimension";
 import { View, ViewOptions, LoadView } from "../core/view";
+import { EnumType, EnumTypeOptions } from "../core/enumType";
 import { RelationType } from "../common/types";
 import { Filter } from "../core/filter";
 import { Clause } from "../core/clause";
@@ -42,6 +43,7 @@ interface ConfigSchema {
     views: ViewParsingOptions[];
     metrics: MetricStrOptions[];
     dimensions: DimensionStrOptions[];
+    enumTypes: EnumTypeOptions[];
 }
 
 interface BuildView {
@@ -60,6 +62,7 @@ export interface ParsedConfig {
     connection: Connection;
     views: View[];
     metrics: Metric[];
+    enumTypes: EnumType[];
     dimensions: Dimension[];
     struct: LoadStruct;
     loadViews: LoadView[];
@@ -82,6 +85,10 @@ interface MetricMap {
     [key: string]: Metric;
 }
 
+interface EnumTypeMap{
+    [key: string]: EnumType;
+}
+
 export class ConfigParser {
     public static parse(configPath: string): ParsedConfig {
         let config: ConfigSchema = yaml.safeLoad(fs.readFileSync(configPath, {
@@ -107,11 +114,13 @@ export class ConfigParser {
         let metricsOpts = config.metrics;
         let viewsOpts = config.views;
         let dimensionsOpts = config.dimensions;
+        let enumTypesOpts = config.enumTypes;
         let parsed: ParsedConfig = {
             adapter: process.env.BLENDB_ADAPTER || "postgres",
             connection: connection,
             views: [],
             metrics: [],
+            enumTypes: [],
             dimensions: [],
             struct: struct,
             loadViews: [],
@@ -120,12 +129,18 @@ export class ConfigParser {
 
         let metMap: MetricMap = {};
         let dimMap: DimensionMap = {};
+        let enumMap: EnumTypeMap = {};
 
         for (let i = 0; i < metricsOpts.length; ++i) {
             let met = new Metric(this.parseMetOpts(metricsOpts[i]));
             parsed.metrics.push(met);
             metMap[met.name] = met;
         }
+        for (let i = 0; i < enumTypesOpts.length; i++) {
+            let enumT = new EnumType((enumTypesOpts[i]));
+            parsed.enumTypes.push(enumT);
+            enumMap[enumT.name] = enumT;
+        }
 
         for (let i = 0; i < dimensionsOpts.length; ++i) {
             let dim = new Dimension(this.parseDimOpts(dimensionsOpts[i], parsed.dimensions));
diff --git a/tslint.json b/tslint.json
index 5d8557a4c479d163bc46ebc9655a640887f6ffe2..4ead9c22a25870942deba8362641383e81035e37 100644
--- a/tslint.json
+++ b/tslint.json
@@ -7,6 +7,6 @@
     "trailing-comma": false,
     "interface-name": false,
     "max-line-length": false,
-    "member-ordering": false
+    "member-ordering": false,    
   }
 }