diff --git a/client/src/app/instance/doc/containers/doc.component.html b/client/src/app/instance/doc/containers/doc.component.html
new file mode 100644
index 0000000000000000000000000000000000000000..d241add0af293f86f4585234bb9ca7898832aea4
--- /dev/null
+++ b/client/src/app/instance/doc/containers/doc.component.html
@@ -0,0 +1,205 @@
+<app-spinner *ngIf="attributeListIsLoading | async"></app-spinner>
+
+<div *ngIf="attributeListIsLoaded | async" class="container">
+    <div class="jumbotron">
+        <div class="row align-items-center">
+            <div class="col-md-12 order-md-1 text-justify text-md-left pr-md-5">
+                <h2 class="mb-3">Export server documentation</h2>
+
+                <h4>URL construction</h4>
+                <p>
+                    To request the server, you need to construct a correct URL. Just below you can find the URL schema and a
+                    description of mandatory parameters:
+                </p>
+                <code>{{ getUrlServer() }}/search/dataset?a=id_attribute&c=id_attribute::operator::value</code>
+
+                <ul>
+                    <li>
+                        <code>dataset</code>: dataset in which to search. See datasets section for available datasets.
+                    </li>
+                    <li>
+                        <code>a</code>: output parameters as attributes id list semicolon separated. See outputs section for available attributes.
+                    </li>
+                    <blockquote>a=1;2;3</blockquote>
+                    <li>
+                        <code>c</code>: criteria list separated with semicolon. A criterion is defined by an id_attribute,
+                        an operator and a value. See operators section for available operators.
+                    </li>
+                    <blockquote>c=3::eq::ping;2::eq::pong</blockquote>
+                </ul>
+
+                <h4>Available parameters</h4>
+
+<!--                <h5>Datasets</h5>-->
+<!--                <div *ngIf="datasetListIsLoading | async">-->
+<!--                    <span class="fas fa-circle-notch fa-spin fa-3x"></span>-->
+<!--                    <span class="sr-only">Loading...</span>-->
+<!--                </div>-->
+<!--                <table *ngIf="datasetListIsLoaded | async" id="table">-->
+<!--                    <tr>-->
+<!--                        <th>Dataset</th>-->
+<!--                        <th>Description</th>-->
+<!--                    </tr>-->
+<!--                    <tr *ngFor="let dataset of datasetList | async">-->
+<!--                        <td>{{ dataset.name }}</td>-->
+<!--                        <td>{{ dataset.description }}</td>-->
+<!--                    </tr>-->
+<!--                </table>-->
+
+                <!-- <h5>Outputs</h5>
+                <div *ngIf="attributeListsIsLoading | async">
+                    <span class="fas fa-circle-notch fa-spin fa-3x"></span>
+                    <span class="sr-only">Loading...</span>
+                </div>
+                <div *ngIf="attributeListsIsLoaded | async" class="row">
+                    <div *ngFor="let dataset of datasetList | async" class="col-auto mb-5">
+                        <h6>{{ dataset.label }} output list</h6>
+                            <table id="table" class="attributes-table p-0">
+                                <tr>
+                                    <th>id</th>
+                                    <th>attribute</th>
+                                </tr>
+                                <tr *ngFor="let attribute of getAttributeList(dataset.name, attributeList | async)">
+                                    <td>{{ attribute.id }}</td>
+                                    <td>{{ attribute.name }}</td>
+                                </tr>
+                            </table>
+                    </div>
+                </div> -->
+
+                <h5>Operators</h5>
+                <table id="table">
+                    <tr>
+                        <th>operator</th>
+                        <th>description</th>
+                        <th>usage</th>
+                        <th>example</th>
+                    </tr>
+                    <tr>
+                        <td>eq</td>
+                        <td>equal to</td>
+                        <td><code>c=id_attribute::eq::value</code></td>
+                        <td><code>c=1::eq::89</code></td>
+                    </tr>
+                    <tr>
+                        <td>neq</td>
+                        <td>not equal to</td>
+                        <td><code>c=id_attribute::neq::value</code></td>
+                        <td><code>c=1::neq::89</code></td>
+                    </tr>
+                    <tr>
+                        <td>gt</td>
+                        <td>greater than</td>
+                        <td><code>c=id_attribute::gt::value</code></td>
+                        <td><code>c=1::gt::1.5</code></td>
+                    </tr>
+                    <tr>
+                        <td>gte</td>
+                        <td>greater than or equal to</td>
+                        <td><code>c=id_attribute::gte::value</code></td>
+                        <td><code>c=1::gte::2</code></td>
+                    </tr>
+                    <tr>
+                        <td>lt</td>
+                        <td>lower than</td>
+                        <td><code>c=id_attribute::lt::value</code></td>
+                        <td><code>c=1::lt::1.5</code></td>
+                    </tr>
+                    <tr>
+                        <td>lte</td>
+                        <td>lower than or equal to</td>
+                        <td><code>c=id_attribute::lte::value</code></td>
+                        <td><code>c=1::lte::2</code></td>
+                    </tr>
+                    <tr>
+                        <td>bw</td>
+                        <td>between</td>
+                        <td><code>c=id_attribute::bw::value_min|value_max</code></td>
+                        <td><code>c=1::bw::10|90</code></td>
+                    </tr>
+                    <tr>
+                        <td>lk</td>
+                        <td>like</td>
+                        <td><code>c=id_attribute::lk::value</code></td>
+                        <td><code>c=1::lk::ping</code></td>
+                    </tr>
+                    <tr>
+                        <td>nlk</td>
+                        <td>not like</td>
+                        <td><code>c=id_attribute::nlk::value</code></td>
+                        <td><code>c=1::nlk::pong</code></td>
+                    </tr>
+                    <tr>
+                        <td>in</td>
+                        <td>in</td>
+                        <td><code>c=id_attribute::in::value_x|value_y|value_z</code></td>
+                        <td><code>c=1::in::ping|pong|paff</code></td>
+                    </tr>
+                    <tr>
+                        <td>nin</td>
+                        <td>not in</td>
+                        <td><code>c=id_attribute::nin::value_x|value_y|value_z</code></td>
+                        <td><code>c=1::nin::ping|pong|paf</code></td>
+                    </tr>
+                    <tr>
+                        <td>nl</td>
+                        <td>is null</td>
+                        <td><code>c=id_attribute::nl</code></td>
+                        <td><code>c=1::nl</code></td>
+                    </tr>
+                    <tr>
+                        <td>nnl</td>
+                        <td>is not null</td>
+                        <td><code>c=id_attribute::nnl</code></td>
+                        <td><code>c=1::nnl</code></td>
+                    </tr>
+                    <tr>
+                        <td>js</td>
+                        <td>json</td>
+                        <td><code>c=id_attribute::js::extension,keyword|operator|value</code></td>
+                        <td><code>c=1::js::PrimaryHDU,ID|eq|45</code></td>
+                    </tr>
+                </table>
+
+                <h4>Examples</h4>
+
+                We supposed to have the dataset ping with following attributes:
+                <table id="table">
+                    <tr>
+                        <th>id</th>
+                        <th>attribute</th>
+                    </tr>
+                    <tr>
+                        <td>1</td>
+                        <td>obs_id</td>
+                    </tr>
+                    <tr>
+                        <td>2</td>
+                        <td>ra</td>
+                    </tr>
+                    <tr>
+                        <td>3</td>
+                        <td>dec</td>
+                    </tr>
+                    <tr>
+                        <td>4</td>
+                        <td>instrument</td>
+                    </tr>
+                </table>
+
+                <blockquote>{{ getUrlServer() }}/search/ping?a=1;2;3&c=1::eq::1</blockquote>
+                <p>This will return the <code>obs_id</code> with its value equals to 1 and display <code>obs_id</code>, <code>RA</code> and <code>DEC</code> as
+                    outputs.</p>
+                <blockquote>
+                    {{ getUrlServer() }}/search/ping?a=1;2;3;4&c=4::in::TEL_1|TEL_2
+                </blockquote>
+                <p>This will return a list of <code>TEL_1</code> or <code>TEL_2</code> observations with all available
+                    outputs.</p>
+                <blockquote>
+                    {{ getUrlServer() }}/search/ping?a=1&c=2::gt::1;3::gt::2
+                </blockquote>
+                <p>This will return a list of <code>obs_id</code> where <code>RA</code> is greater than 1 and <code>DEC</code> is greater than 2</p>
+            </div>
+        </div>
+    </div>
+</div>
diff --git a/client/src/app/instance/doc/containers/doc.component.ts b/client/src/app/instance/doc/containers/doc.component.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4ba2de8f1722d03909ad9bcd0b79a77b988e215b
--- /dev/null
+++ b/client/src/app/instance/doc/containers/doc.component.ts
@@ -0,0 +1,88 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Component, OnInit } from '@angular/core';
+
+import { Store } from '@ngrx/store';
+import { Observable } from 'rxjs';
+
+import * as documentationActions from 'src/app/instance/store/actions/documentation.actions';
+import * as datasetActions from 'src/app/metamodel/actions/dataset.actions';
+import * as datasetFamilySelector from 'src/app/metamodel/selectors/dataset-family.selector';
+import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector';
+import {Attribute, Dataset, DatasetFamily, Survey} from 'src/app/metamodel/models';
+import { environment } from 'src/environments/environment';
+import * as authSelector from "../../../auth/auth.selector";
+import * as instanceSelector from "../../../metamodel/selectors/instance.selector";
+import * as surveySelector from "../../../metamodel/selectors/survey.selector";
+import * as attributeSelector from "../../../metamodel/selectors/attribute.selector";
+
+@Component({
+    selector: 'app-doc',
+    templateUrl: 'doc.component.html',
+    styleUrls: ['../doc.component.scss']
+})
+/**
+ * @class
+ * @classdesc Documentation container.
+ *
+ * @implements OnInit
+ */
+export class DocComponent implements OnInit {
+    public instanceSelected: Observable<string>;
+    public datasetSelected: Observable<string>;
+    public attributeListIsLoading: Observable<boolean>;
+    public attributeListIsLoaded: Observable<boolean>;
+    public attributeList: Observable<Attribute[]>;
+    // public isAuthenticated: Observable<boolean>;
+    // public datasetFamilyListIsLoading: Observable<boolean>;
+    // public datasetFamilyListIsLoaded: Observable<boolean>;
+    // public datasetFamilyList: Observable<DatasetFamily[]>;
+    // public surveyListIsLoading: Observable<boolean>;
+    // public surveyListIsLoaded: Observable<boolean>;
+    // public surveyList: Observable<Survey[]>;
+    // public datasetListIsLoading: Observable<boolean>;
+    // public datasetListIsLoaded: Observable<boolean>;
+    // public datasetList: Observable<Dataset[]>;
+
+    constructor(private store: Store<{ }>) {
+        this.instanceSelected = store.select(instanceSelector.selectInstanceNameByRoute);
+        this.datasetSelected = store.select(datasetSelector.selectDatasetNameByRoute);
+        this.attributeListIsLoading = store.select(attributeSelector.selectAttributeListIsLoading);
+        this.attributeListIsLoaded = store.select(attributeSelector.selectAttributeListIsLoaded);
+        this.attributeList = store.select(attributeSelector.selectAllAttributes);
+        // this.isAuthenticated = store.select(authSelector.selectIsAuthenticated);
+        // this.datasetFamilyListIsLoading = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoading);
+        // this.datasetFamilyListIsLoaded = store.select(datasetFamilySelector.selectDatasetFamilyListIsLoaded);
+        // this.datasetFamilyList = store.select(datasetFamilySelector.selectAllDatasetFamilies);
+        // this.surveyListIsLoading = store.select(surveySelector.selectSurveyListIsLoading);
+        // this.surveyListIsLoaded = store.select(surveySelector.selectSurveyListIsLoaded);
+        // this.surveyList = store.select(surveySelector.selectAllSurveys);
+        // this.datasetListIsLoading = store.select(datasetSelector.selectDatasetListIsLoading);
+        // this.datasetListIsLoaded = store.select(datasetSelector.selectDatasetListIsLoaded);
+        // this.datasetList = store.select(datasetSelector.selectAllDatasets);
+    }
+
+    ngOnInit() {
+        this.store.dispatch(documentationActions.loadAttributeList());
+    }
+
+    /**
+     * Returns strict url address.
+     *
+     * @return string
+     */
+    getUrlServer(): string {
+        if (!environment.apiUrl.startsWith('http')) {
+            const url = window.location;
+            return url.protocol + '//' + url.host + environment.apiUrl;
+        }
+        return environment.apiUrl;
+    }
+}
diff --git a/client/src/app/instance/store/actions/documentation.actions.ts b/client/src/app/instance/store/actions/documentation.actions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d2da6760840f913e1261cff8e014ec11048aa438
--- /dev/null
+++ b/client/src/app/instance/store/actions/documentation.actions.ts
@@ -0,0 +1,12 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { createAction } from '@ngrx/store';
+
+export const loadAttributeList = createAction('[Documentation] Load Attribute List');
diff --git a/client/src/app/instance/store/effects/documentation.effects.ts b/client/src/app/instance/store/effects/documentation.effects.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b43a756ff76b9df2b76280d9a9bd7d0679314eb7
--- /dev/null
+++ b/client/src/app/instance/store/effects/documentation.effects.ts
@@ -0,0 +1,211 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { Injectable } from '@angular/core';
+
+import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects';
+import { Store, Action  } from '@ngrx/store';
+import { of } from 'rxjs';
+import { map, tap, mergeMap, catchError } from 'rxjs/operators';
+import { ToastrService } from 'ngx-toastr';
+
+import { criterionToString, stringToCriterion } from '../models';
+import { SearchService } from '../services/search.service';
+import * as documentationActions from '../actions/documentation.actions';
+import * as searchActions from '../actions/search.actions';
+import * as attributeActions from 'src/app/metamodel/actions/attribute.actions';
+import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector';
+import * as criteriaFamilyActions from 'src/app/metamodel/actions/criteria-family.actions';
+import * as outputFamilyActions from 'src/app/metamodel/actions/output-family.actions';
+import * as outputCategoryActions from 'src/app/metamodel/actions/output-category.actions';
+import * as datasetSelector from 'src/app/metamodel/selectors/dataset.selector';
+import * as searchSelector from '../selectors/search.selector';
+
+@Injectable()
+export class DocumentationEffects {
+    loadAttributeList$ = createEffect(() =>
+        this.actions$.pipe(
+            ofType(documentationActions.loadAttributeList),
+            concatLatestFrom(() => this.store.select(datasetSelector.selectDatasetNameByRoute)),
+            mergeMap(([action, datasetName]) => {
+                console.log('ok');
+                return of(attributeActions.loadAttributeList());
+            })
+        )
+    );
+
+    // initSearch$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.initSearch),
+    //         concatLatestFrom(() => [
+    //             this.store.select(datasetSelector.selectDatasetNameByRoute),
+    //             this.store.select(searchSelector.selectCurrentDataset),
+    //             this.store.select(searchSelector.selectPristine),
+    //             this.store.select(searchSelector.selectStepsByRoute)
+    //         ]),
+    //         mergeMap(([action, datasetName, currentDataset, pristine, steps]) => {
+    //             // User has changed dataset: reload initial state + init search
+    //             if (datasetName && currentDataset && datasetName !== currentDataset) {
+    //                 return of(searchActions.restartSearch());
+    //             }
+    //
+    //             // User has selected a dataset or page is reloaded: load dataset metamodel
+    //             if (datasetName && pristine) {
+    //                 let actions: Action[] = [
+    //                     searchActions.changeCurrentDataset({ currentDataset: datasetName }),
+    //                     attributeActions.loadAttributeList(),
+    //                     criteriaFamilyActions.loadCriteriaFamilyList(),
+    //                     outputFamilyActions.loadOutputFamilyList(),
+    //                     outputCategoryActions.loadOutputCategoryList()
+    //                 ];
+    //                 if (steps) {
+    //                     if(steps[0] === '1') {
+    //                         actions.push(searchActions.checkCriteria());
+    //                     }
+    //                     if(steps[1] === '1') {
+    //                         actions.push(searchActions.checkOutput());
+    //                     }
+    //                     if(steps[2] === '1') {
+    //                         actions.push(searchActions.checkResult());
+    //                     }
+    //                 }
+    //                 return actions;
+    //             }
+    //
+    //             // User come back to the search module: reload initial state
+    //             if(!datasetName && !pristine) {
+    //                 return of(searchActions.resetSearch());
+    //             }
+    //
+    //             // User change step and it's the same search: No action
+    //             return of({ type: '[No Action] Init Search' });
+    //         })
+    //     )
+    // );
+    //
+    // restartSearch$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.restartSearch),
+    //         map(() => searchActions.initSearch())
+    //     )
+    // );
+    //
+    // loadDefaultFormParameters$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.loadDefaultFormParameters),
+    //         concatLatestFrom(() => [
+    //             this.store.select(attributeSelector.selectAllAttributes),
+    //             this.store.select(searchSelector.selectCriteriaListByRoute),
+    //             this.store.select(searchSelector.selectOutputListByRoute)
+    //         ]),
+    //         mergeMap(([action, attributeList, criteriaList, outputList]) => {
+    //             // Update criteria list
+    //             let defaultCriteriaList = [];
+    //             if (criteriaList) {
+    //                 // Build criteria list with the URL query parameters (c)
+    //                 defaultCriteriaList = criteriaList.split(';').map((c: string) => {
+    //                     const params = c.split('::');
+    //                     const attribute = attributeList.find(a => a.id === parseInt(params[0], 10));
+    //                     return stringToCriterion(attribute, params);
+    //                 });
+    //             } else {
+    //                 // Build default criteria list with the attribute list metamodel configuration
+    //                 defaultCriteriaList = attributeList
+    //                     .filter(attribute => attribute.id_criteria_family && attribute.search_type && attribute.min)
+    //                     .map(attribute => stringToCriterion(attribute));
+    //             }
+    //
+    //             // Update output list
+    //             let defaultOutputList = [];
+    //             if (outputList) {
+    //                 // Build output list with the URL query parameters (a)
+    //                 defaultOutputList = outputList.split(';').map((o: string) => parseInt(o, 10));
+    //             } else {
+    //                 // Build default output list with the attribute list metamodel configuration
+    //                 defaultOutputList = attributeList
+    //                     .filter(attribute => attribute.selected && attribute.id_output_category)
+    //                     .map(attribute => attribute.id);
+    //             }
+    //
+    //             // Returns actions and mark the form as dirty
+    //             return [
+    //                 searchActions.updateCriteriaList({ criteriaList: defaultCriteriaList }),
+    //                 searchActions.updateOutputList({ outputList: defaultOutputList }),
+    //                 searchActions.markAsDirty()
+    //             ];
+    //         })
+    //     )
+    // );
+    //
+    // retrieveDataLength$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.retrieveDataLength),
+    //         concatLatestFrom(() => [
+    //             this.store.select(datasetSelector.selectDatasetNameByRoute),
+    //             this.store.select(searchSelector.selectCriteriaList)
+    //         ]),
+    //         mergeMap(([action, datasetName, criteriaList]) => {
+    //             let query = datasetName + '?a=count';
+    //             if (criteriaList.length > 0) {
+    //                 query += '&c=' + criteriaList.map(criterion => criterionToString(criterion)).join(';');
+    //             }
+    //
+    //             return this.searchService.retrieveDataLength(query)
+    //                 .pipe(
+    //                     map((response: { nb: number }[]) => searchActions.retrieveDataLengthSuccess({ length: response[0].nb })),
+    //                     catchError(() => of(searchActions.retrieveDataLengthFail()))
+    //                 )
+    //         })
+    //     )
+    // );
+    //
+    // retrieveDataLengthFail$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.retrieveDataLengthFail),
+    //         tap(() => this.toastr.error('Loading Failed', 'The search data length loading failed'))
+    //     ), { dispatch: false}
+    // );
+    //
+    // retrieveData$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.retrieveData),
+    //         concatLatestFrom(() => [
+    //             this.store.select(datasetSelector.selectDatasetNameByRoute),
+    //             this.store.select(searchSelector.selectCriteriaList),
+    //             this.store.select(searchSelector.selectOutputList)
+    //         ]),
+    //         mergeMap(([action, datasetName, criteriaList, outputList]) => {
+    //             let query = datasetName + '?a=' + outputList.join(';');
+    //             if (criteriaList.length > 0) {
+    //                 query += '&c=' + criteriaList.map(criterion => criterionToString(criterion)).join(';');
+    //             }
+    //             query += '&p=' + action.pagination.nbItems + ':' + action.pagination.page;
+    //             query += '&o=' + action.pagination.sortedCol + ':' + action.pagination.order;
+    //
+    //             return this.searchService.retrieveData(query)
+    //                 .pipe(
+    //                     map((data: any[]) => searchActions.retrieveDataSuccess({ data })),
+    //                     catchError(() => of(searchActions.retrieveDataFail()))
+    //                 )
+    //         })
+    //     )
+    // );
+    //
+    // retrieveDataFail$ = createEffect(() =>
+    //     this.actions$.pipe(
+    //         ofType(searchActions.retrieveDataFail),
+    //         tap(() => this.toastr.error('Loading Failed', 'The search data loading failed'))
+    //     ), { dispatch: false}
+    // );
+
+    constructor(
+        private actions$: Actions,
+        private store: Store<{ }>
+    ) {}
+}
diff --git a/client/src/app/instance/store/effects/index.ts b/client/src/app/instance/store/effects/index.ts
index 296d89b24794a19ce38357ac7eab009ed9234257..6c5a834023827b54a609d049daa42baa9b829be3 100644
--- a/client/src/app/instance/store/effects/index.ts
+++ b/client/src/app/instance/store/effects/index.ts
@@ -1,9 +1,11 @@
 import { MetamodelEffects } from './metamodel.effects';
 import { SampEffects } from "./samp.effects";
 import { SearchEffects } from "./search.effects";
+import { DocumentationEffects } from "./documentation.effects";
 
 export const instanceEffects = [
     MetamodelEffects,
     SampEffects,
-    SearchEffects
+    SearchEffects,
+    DocumentationEffects
 ];