# Undo or redo an action

Undo an action by using the [Undo method](https://help.qlik.com/en-US/sense-developer/November2024/Subsystems/EngineJSONAPI/Content/service-doc-undo.htm) and redo it by using the [Redo method](https://help.qlik.com/en-US/sense-developer/November2024/Subsystems/EngineJSONAPI/Content/service-doc-redo.htm).

## Example

[](https://help.qlik.com/en-US/sense-developer/Subsystems/EngineAPI/Content/Sense_EngineAPI/UndoAndRedo/undo-redo.htm)

#### The goal of this example is to:

* Create a transient object that lists the number of possible undos and redos.
* Check the number of possible undos and redos.
* Create a sheet and add two children (list objects) to that sheet.
* Check the number of possible undos and redos.
* Undo the creation of the last list object.
* Check the number of possible undos and redos.
* Redo the creation of the list object.
* Check the number of possible undos and redos.
* Clear the undo buffer.
* Check the number of possible undos and redos.

1. Create a transient object that lists the number of possible undos and redos. qUndoInfoDef: {} is added in the object definition to enable retrieving the number of undos and redos. The list is named UndoList01 ( "qId": "UndoList01").

   The client sends:

   ```
   {
     "jsonrpc": "2.0",
     "id": 1,
     "method": "CreateSessionObject",
     "handle": 1,
     "params": [
       {
         "qInfo": {
           "qId": "UndoList01",
           "qType": "Undo"
         },
         "qUndoInfoDef": {}
       }
     ]
   }
   ```

   The engine returns:

   ```
   {
     "jsonrpc": "2.0",
     "id": 1,
     "result": {
       "qReturn": {
         "qType": "GenericObject",
         "qHandle": 2
       }
     },
     "change": [
       2
     ]
   }
   ```

   The undo list is created and has 2 as a handle.

2. Get the layout of the undo list. The handle of the request is 2 because the list has 2 as a handle.

   The client sends:

   ```
   {
     "jsonrpc": "2.0",
     "id": 2,
     "method": "GetLayout",
     "handle": 2,
     "params": []
   }
   ```

   The engine returns:

   ```
   {
     "jsonrpc": "2.0",
     "id": 2,
     "result": {
       "qLayout": {
         "qInfo": {
           "qId": "UndoList01",
           "qType": "Undo"
         },
         "qMeta": {},
         "qSelectionInfo": {},
         "qUndoInfo": {
           "qUndoCount": 0,
           "qRedoCount": 0
         }
       }
     }
   }
   ```

   Since no action (create/delete, update) has been performed, the undo and redo counters are set to 0 (qUndoCount and qRedoCount are set to 0).

3. Create a sheet Sheet01. The handle of the request is 1 because the [CreateObject method](https://help.qlik.com/en-US/sense-developer/November2024/Subsystems/EngineJSONAPI/Content/service-doc-cloneobject.htm) applies at app level and the handle of the app is 1.

   The client sends:

   ```
   {
     "jsonrpc": "2.0",
     "id": 3,
     "method": "CreateObject",
     "handle": 1,
     "params": [
       {
         "title": "Sheet 1",
         "description": "Description of sheet 1",
         "qInfo": {
           "qId": "Sheet01",
           "qType": "sheet"
         },
         "qChildListDef": {
           "qData": {
             "title": "/title",
             "description": "/description",
             "meta": "/meta",
             "order": "/order",
             "id": "/qInfo/qId",
             "type": "/qInfo/qType",
             "lb": "/qListObjectDef",
             "hc": "/qHyperCubeDef"
           }
         }
       }
     ]
   }
   ```

   The engine returns:

   ```
   {
     "jsonrpc": "2.0",
     "id": 3,
     "result": {
       "qReturn": {
         "qType": "GenericObject",
         "qHandle": 3
       },
       "qInfo": {
         "qId": "Sheet01",
         "qType": "sheet"
       }
     },
     "change": [
       2,
       3
     ]
   }
   ```

   The sheet Sheet01 is created and has 3 as a handle.

4. Create a list object LI01 in the sheet (qId set to LI01).The handle of the request is 3 which is the handle of the sheet. The list object LI01 is a child of the sheet.

   The client sends:

   { "jsonrpc": "2.0", "id": 4, "method": "CreateChild", "handle": 3, "params": [ { "qInfo": { "qId": "LI01", "qType": "ListObject" }, "qListObjectDef": { "qStateName": "$", "qLibraryId": "", "qDef": { "qFieldDefs": [ "Country" ], "qFieldLabels": [ "Country Label" ], "qSortCriterias": [ { "qSortByLoadOrder": 1 } ] }, "qInitialDataFetch": [ { "qTop": 0, "qHeight": 1, "qLeft": 0, "qWidth": 1 } ] } } ] }

   The engine returns:

   { "jsonrpc": "2.0", "id": 4, "result": { "qReturn": { "qType": "GenericObject", "qHandle": 4 }, "qInfo": { "qId": "LI01", "qType": "ListObject" } }, "change": [ 4 ] }

   The list object LI01 is created . Its handle is 4.

5. Create a list object LI02 in the sheet (qId set to LI02).The handle of the request is 3, which is the handle of the sheet. The list object LI02 is a child of the sheet.

   The client sends:

   { "jsonrpc": "2.0", "id": 5, "method": "CreateChild", "handle": 3, "params": [ { "qInfo": { "qId": "LI02", "qType": "ListObject" }, "qListObjectDef": { "qStateName": "$", "qLibraryId": "", "qDef": { "qFieldDefs": [ "Country" ], "qFieldLabels": [ "Country Label" ], "qSortCriterias": [ { "qSortByLoadOrder": 1 } ] }, "qInitialDataFetch": [ { "qTop": 0, "qHeight": 1, "qLeft": 0, "qWidth": 1 } ] } } ] }

   The engine returns:

   { "jsonrpc": "2.0", "id": 5, "result": { "qReturn": { "qType": "GenericObject", "qHandle": 5 }, "qInfo": { "qId": "LI02", "qType": "ListObject" } }, "change": [ 5 ] }

   The list object LB01 is created . Its handle is 5.

6. Get the layout of the undo list. The handle of the request is 2 because the list has 2 as a handle.

   The client sends:

   { "jsonrpc": "2.0", "id": 6, "method": "GetLayout", "handle": 2, "params": [] }

   The engine returns:

   { "jsonrpc": "2.0", "id": 6, "result": { "qLayout": { "qInfo": { "qId": "UndoList01", "qType": "Undo" }, "qMeta": {}, "qSelectionInfo": {}, "qUndoInfo": { "qUndoCount": 3, "qRedoCount": 0 } } } }

   The number of possible undos (qUndoCount) is 3 and the number of possible redos (qRedoCount) is 0.

7. Undo the last list object creation. The handle of the request is 1 because the [Undo method](https://help.qlik.com/en-US/sense-developer/November2024/Subsystems/EngineJSONAPI/Content/service-doc-undo.htm) applies at the app level and the handle of the app is 1.

   The client sends:

   { "jsonrpc": "2.0", "id": 7, "method": "Undo", "handle": 1, "params": [] }

   The engine returns:

   { "jsonrpc": "2.0", "id": 7, "result": { "qSuccess": true }, "change": [ 2 ], "close": [ 5 ] }

   The undo is successful (qSuccess is set to true). The list object LI02 is removed.

8. Get the layout of the undo list. The handle of the request is 2 because the list uses 2 as a handle.

   The client sends:

   { "jsonrpc": "2.0", "id": 8, "method": "GetLayout", "handle": 2, "params": [] }

   The engine returns:

   { "jsonrpc": "2.0", "id": 8, "result": { "qLayout": { "qInfo": { "qId": "UndoList01", "qType": "Undo" }, "qMeta": {}, "qSelectionInfo": {}, "qUndoInfo": { "qUndoCount": 2, "qRedoCount": 1 } } } }

   The number of possible undos (qUndoCount) is 2 and the number of possible redos (qRedoCount) is 1.

9. Redo the list object creation. The handle of the request is 1 because the [Redo method](https://help.qlik.com/en-US/sense-developer/November2024/Subsystems/EngineJSONAPI/Content/service-doc-redo.htm) applies at the app level and the handle of the app is 1.

   The client sends:

   { "jsonrpc": "2.0", "id": 9, "method": "Redo", "handle": 1, "params": [] }

   The engine returns:

   { "jsonrpc": "2.0", "id": 9, "result": { "qSuccess": true }, "change": [ 2 ] }

   The redo is successful (qSuccess is set to true). The list object LI02 is created.

10. Get the layout of the undo list. The handle of the request is 2 because the list uses 2 as a handle.

    The client sends:

    { "jsonrpc": "2.0", "id": 10, "method": "GetLayout", "handle": 2, "params": [] }

    The engine returns:

    { "jsonrpc": "2.0", "id": 10, "result": { "qLayout": { "qInfo": { "qId": "UndoList01", "qType": "Undo" }, "qMeta": {}, "qSelectionInfo": {}, "qUndoInfo": { "qUndoCount": 3, "qRedoCount": 0 } } } }

    The number of possible undos (qUndoCount) is 3 and the number of possible redos (qRedoCount) is 0.

11. Clear the undo buffer. The handle of the request is 1 because the [ClearUndoBuffer method](https://help.qlik.com/en-US/sense-developer/November2024/Subsystems/EngineJSONAPI/Content/service-doc-clearundobuffer.htm) applies at the app level and the handle of the app is 1.

    The client sends:

    { "jsonrpc": "2.0", "id": 11, "method": "ClearUndoBuffer", "handle": 1, "params": [] }

    The engine returns:

    { "jsonrpc": "2.0", "id": 11, "result": {}, "change": [ 2 ] }

12. Get the layout of the undo list. The handle of the request is 2 because the list uses 2 as a handle.

    The client sends:

    { "jsonrpc": "2.0", "id": 12, "method": "GetLayout", "handle": 2, "params": [] }

    The engine returns:

    { "jsonrpc": "2.0", "id": 12, "result": { "qLayout": { "qInfo": { "qId": "UndoList01", "qType": "Undo" }, "qMeta": {}, "qSelectionInfo": {}, "qUndoInfo": { "qUndoCount": 0, "qRedoCount": 0 } } } }

    The undo buffer is cleared. The number of possible undos (qUndoCount) is 0 and the number of possible redos (qRedoCount) is 0.