diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js
index ce905d8bd1f8476c38795a03a78347c85ed9cda3..d2119dd2694ab2aa24186a180f3b8bb67b82518f 100644
--- a/src/libs/routes/api.js
+++ b/src/libs/routes/api.js
@@ -6,6 +6,8 @@ const libs = `${process.cwd()}/libs`;
 
 const config = require(`${libs}/config`);
 
+const classes = require('./class');
+
 const cache = require('apicache').options({ debug: config.debug }).middleware;
 
 const enrollment = require('./enrollment');
@@ -31,6 +33,7 @@ api.get('/', (req, res) => {
 // mount API routes
 api.use('/user', user);
 api.use('/simulation', simulation);
+api.use('/class', cache('15 day'), classes);
 api.use('/enrollment', cache('1 day'), enrollment);
 api.use('/state', cache('15 day'), state);
 api.use('/region', cache('15 day'), region);
diff --git a/src/libs/routes/class.js b/src/libs/routes/class.js
new file mode 100644
index 0000000000000000000000000000000000000000..dc0f02588ef387ad7fb6d6503773754de4a54af5
--- /dev/null
+++ b/src/libs/routes/class.js
@@ -0,0 +1,247 @@
+const express = require('express');
+
+const classApp = express.Router();
+
+const libs = `${process.cwd()}/libs`;
+
+const log = require(`${libs}/log`)(module);
+
+const squel = require('squel');
+
+const query = require(`${libs}/middlewares/query`);
+
+const response = require(`${libs}/middlewares/response`);
+
+const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`);
+
+let rqfCount = new ReqQueryFields();
+// Complete range of the enrollments dataset.
+// Returns a tuple of start and ending years of the complete enrollments dataset.
+classApp.get('/year_range', (req, res, next) => {
+    req.sql.from('turma')
+    .field('MIN(turma.ano_censo)', 'start_year')
+    .field('MAX(turma.ano_censo)', 'end_year');
+    next();
+}, query, response('range'));
+
+classApp.get('/location', (req, res, next) => {
+    req.sql = squel.select()
+    .field('id')
+    .field('descricao', 'name')
+    .from('localizacao');
+    next();
+}, query, response('location'));
+
+// Returns all adm dependencies
+classApp.get('/adm_dependency', (req, res, next) => {
+    req.sql.from('dependencia_adm')
+    .field('id')
+    .field('nome', 'name')
+    .where('id <= 4');
+    next();
+}, query, response('adm_dependency'));
+
+classApp.get('/adm_dependency_detailed', (req, res, next) => {
+    req.sql.from('dependencia_adm')
+    .field('id', 'id')
+    .field('nome', 'name');
+    next();
+}, query, response('adm_dependency_detailed'));
+
+// Returns all periods avaible
+classApp.get('/period', (req, res, next) => {
+    req.sql.from('turma_turno')
+    .field('id')
+    .field('nome', 'name');
+    next();
+}, query, response('period'));
+
+// Returns all educational levels avaible
+classApp.get('/education_level', (req, res, next) => {
+    req.sql.from('etapas_mod_ensino_segmento')
+    .field('id')
+    .field('nome', 'name');
+    next();
+}, query, response('education_level'));
+
+rqfCount.addField({
+    name: 'filter',
+    field: false,
+    where: true
+}).addField({
+    name: 'dims',
+    field: true,
+    where: false
+}).addValue({
+    name: 'city',
+    table: 'municipio',
+    tableField: 'nome',
+    resultField: 'city_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'municipio_id',
+        table: 'turma'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'municipio_id',
+        foreignTable: 'turma'
+    }
+}).addValue({
+    name: 'state',
+    table: 'estado',
+    tableField: 'nome',
+    resultField: 'state_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'estado_id',
+        table: 'turma'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'estado_id',
+        foreignTable: 'turma'
+    }
+}).addValue({
+    name: 'region',
+    table: 'regiao',
+    tableField: 'nome',
+    resultField: 'region_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'regiao_id',
+        foreignTable: 'turma'
+    }
+}).addValue({
+    name: 'min_year',
+    table: 'turma',
+    tableField: 'ano_censo',
+    resultField: 'year',
+    where: {
+        relation: '>=',
+        type: 'integer',
+        field: 'ano_censo'
+    }
+}).addValue({
+    name: 'max_year',
+    table: 'turma',
+    tableField: 'ano_censo',
+    resultField: 'year',
+    where: {
+        relation: '<=',
+        type: 'integer',
+        field: 'ano_censo'
+    }
+}).addValue({
+    name:'adm_dependency',
+    table: 'dependencia_adm',
+    tableField: 'id',
+    resultField: 'adm_dependency_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'dependencia_adm_id',
+        foreignTable: 'turma'
+    }
+}).addValue({
+    name: 'location',
+    table: 'localizacao',
+    tableField: 'descricao',
+    resultField: 'location_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'localizacao_id',
+        foreignTable: 'turma'
+    }
+}).addValue({
+  name:'education_level',
+  table: 'etapas_mod_ensino_segmento ',
+  tableField: 'id',
+  resultField: 'education_level_name',
+  where: {
+    relation: '=',
+    type: 'integer',
+    field: 'id'
+  },
+  join: {
+    primary: 'id',
+    foreign: 'etapas_mod_ensino_segmento_id',
+    foreignTable: 'turma'
+  }
+}).addValue({
+    name: 'adm_dependency_detailed',
+    table: 'dependencia_adm',
+    tableField: 'nome',
+    resultField: 'adm_dependency_detailed_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: 'id',
+        foreign: 'dependencia_adm_priv',
+        foreignTable: 'turma'
+    }
+}).addValue({
+  name:'period',
+  table: 'turma_turno',
+  tableField: 'id',
+  resultField: 'period_name',
+  where: {
+      relation: '=',
+      type: 'integer',
+      field: 'id'
+  },
+  join: {
+      primary: 'id',
+      foreign: 'turno',
+      foreignTable: 'turma'
+  }
+}).addValue({
+    name: 'school',
+    table: 'escola',
+    tableField: 'nome_escola',
+    resultField: 'school_name',
+    where: {
+        relation: '=',
+        type: 'integer',
+        field: 'id'
+    },
+    join: {
+        primary: ['id', 'ano_censo'],
+        foreign: ['escola_id', 'ano_censo'],
+        foreignTable: 'turma'
+    }
+});
+
+
+classApp.get('/', rqfCount.parse(), rqfCount.build(), (req, res, next) => {
+  log.debug(req.sql.toParam());
+   req.sql.field('COUNT(turma.id)', 'total')
+   .field("'Brasil'", 'name')
+   .field('turma.ano_censo', 'year')
+   .from('turma')
+   .group('turma.ano_censo')
+   .order('turma.ano_censo')
+   .where('turma.tipo_turma_id = 0 OR turma.tipo_turma_id = 1 OR turma.tipo_turma_id = 2 OR turma.tipo_turma_id = 3');
+   next();
+}, query, response('class'));
+
+module.exports = classApp;
diff --git a/src/test/class.js b/src/test/class.js
new file mode 100644
index 0000000000000000000000000000000000000000..3cf5f354e384a1e94e8362590d2ac0a133ee6fbe
--- /dev/null
+++ b/src/test/class.js
@@ -0,0 +1,173 @@
+process.env.NODE_ENV = 'test';
+
+const chai = require('chai');
+
+const dirtyChai = require('dirty-chai');
+
+chai.use(dirtyChai);
+
+const chaiXml = require('chai-xml');
+
+chai.use(chaiXml);
+
+const chaiHttp = require('chai-http');
+
+const assert = chai.assert;
+
+const expect = chai.expect;
+
+const should = chai.should(); // actually call the function
+
+const libs = `${process.cwd()}/libs`;
+
+const server = require(`${libs}/app`);
+
+chai.use(chaiHttp);
+describe('request enrollments', () => {
+    it('should list the locations', (done) => {
+        chai.request(server)
+            .get('/api/v1/class/location')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the education level', (done) => {
+        chai.request(server)
+            .get('/api/v1/class/education_level')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the administrative dependencies', (done) => {
+        chai.request(server)
+            .get('/api/v1/class/adm_dependency_detailed')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the administrative dependencies detailed', (done) => {
+        chai.request(server)
+            .get('/api/v1/class/adm_dependency')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list the periods', (done) => {
+        chai.request(server)
+            .get('/api/v1/enrollment/period')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('id');
+                res.body.result[0].should.have.property('name');
+                done();
+            });
+    });
+
+    it('should list class', (done) => {
+        chai.request(server)
+            .get('/api/v1/class')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('name');
+                res.body.result[0].should.have.property('total');
+                done();
+            });
+    });
+
+    it('should list class with valid filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/class?filter=state:41')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('name');
+                res.body.result[0].should.have.property('total');
+                done();
+            });
+    });
+
+    it('should list class with valid dimensions', (done) => {
+        chai.request(server)
+            .get('/api/v1/class?dims=region,state,adm_dependency,location&filter=region:1')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('region_name');
+                res.body.result[0].should.have.property('state_name');
+                res.body.result[0].should.have.property('adm_dependency_name');
+                res.body.result[0].should.have.property('location_name');
+                res.body.result[0].should.have.property('total');
+                done();
+            });
+    });
+
+    it('should list class with invalid dimensions', (done) => {
+        chai.request(server)
+            .get('/api/v1/class?dims=foo,bar')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('name');
+                res.body.result[0].should.have.property('total');
+                done();
+            });
+    });
+
+    it('should list class with valid dimensions and filters', (done) => {
+        chai.request(server)
+            .get('/api/v1/class?dims=region,state,education_level,school,period&filter=min_year:2015,max_year:2015,city:4106902')
+            .end((err, res) => {
+                res.should.have.status(200);
+                res.should.be.json;
+                res.body.should.have.property('result');
+                res.body.result.should.be.a('array');
+                res.body.result[0].should.have.property('region_name');
+                res.body.result[0].should.have.property('state_name');
+                res.body.result[0].should.have.property('school_name');
+                res.body.result[0].should.have.property('education_level_name');
+                res.body.result[0].should.have.property('total');
+                res.body.result[0].should.have.property('year');
+                done();
+            });
+    });
+});