# Notebooks API Design Documentation ## Contents 1. [**Notebook Examples**](#notebook-examples) 2. [**Note APIs**](#notes-apis) 3. [**Paragraph APIs**](#paragraph-apis) 4. [**Future Work**](#future-work) 5. [**References**](#references) ## OpenSearch Dashboards Notebooks REST APIs **_NOTE:_** The Notebook/Paragraph structure used in body & responses, are with Zeppelin Backend Adaptor. The structure of noteboook and paragraph changes with change in backend, but format of request body and response body remains the same. ## Notebook Examples - **Default Notebook** ``` { id: 'note_5f4b9eed-5898-4b39-ba6c-755c0fadd84e', dateCreated: '2020-08-20T18:00:59.845Z', name: 'test 1', dateModified: '2020-08-20T18:37:56.844Z', pluginVersion: '7.9.0', backend: 'Default', paragraphs: [ { output: [{ result: '# Type your input here', outputType: 'MARKDOWN', execution_time: '0s' }], input: { inputText: '# Type your input here', inputType: 'MARKDOWN' }, dateCreated: '2020-08-20T18:00:59.845Z', dateModified: '2020-08-20T18:00:59.845Z', id: 'paragraph_1a710988-ec19-4caa-83cc-38eb609427d1', }, { output: [{ result: '', outputType: 'VISUALIZATION', execution_time: '0s' }], input: { inputText: '{"viewMode":"view","panels":{"1":{"gridData":{"x":1,"y":0,"w":44,"h":20,"i":"1"},"type":"visualization","explicitInput":{"id":"1","savedObjectId":"935afa20-e0cd-11e7-9d07-1398ccfcefa3","vis":null}}},"isFullScreenMode":false,"filters":[],"useMargins":false,"id":"i3ccc6260-e314-11ea-9f99-b37e94bb02ca","timeRange":{"to":"2020-08-20T18:37:44.710Z","from":"2020-07-21T18:37:44.710Z"},"title":"embed_viz_i3ccc6260-e314-11ea-9f99-b37e94bb02ca","query":{"query":"","language":"lucene"},"refreshConfig":{"pause":true,"value":15}}', inputType: 'VISUALIZATION', }, dateCreated: '2020-08-20T18:37:44.809Z', dateModified: '2020-08-20T18:37:56.844Z', id: 'paragraph_6d3237a9-6486-4f93-aa25-0a1c838faabd', }, ], }; ``` - **Zeppelin Notebook** ``` { paragraphs: [ { text: "%md\n Input", dateUpdated: '2020-08-20 21:15:04.590', config: {}, settings: { params: {}, forms: {} }, results: { code: 'SUCCESS', msg: [ { type: 'HTML', data: '
\nInput
', }, ], }, apps: [], runtimeInfos: {}, progressUpdateIntervalMs: 500, jobName: 'paragraph_1597958104590_901298942', id: 'paragraph_1596519508360_932236116', dateCreated: '2020-08-20 21:15:04.590', status: 'READY', }, ], name: 'Embed Vizualization', id: '2FJH8PW8K', defaultInterpreterGroup: 'spark', version: '0.9.0-preview2', noteParams: {}, noteForms: {}, angularObjects: {}, config: { isZeppelinNotebookCronEnable: false }, info: {}, }; ``` ## Notes APIs 1. **Fetch all the notebooks available →** returns a list of notebook id and paths ``` GET api/notebooks/ RESPONSE BODY { "data": [ { "id": "2FF3GW3H8", "path": "/Embed Viz" }, { "id": "2FHEP953H", "path": "/Log Analysis" }, { "id": "2FES7PY77", "path": "/Post-mortem Report" }, { "id": "2FFAMT6VV", "path": "/test 1" } ] } ``` 2. **Get all paragraphs of a notebook →** returns list of paragraphs ``` GET api/notebooks/note/{noteId} RESPONSE BODY // list of Paragraphs { "paragraphs": [ { "text": "%md\n# This is markdown test", "user": "anonymous", "dateUpdated": "Aug 11, 2020 8:24:38 AM", "config": { "tableHide": true, "editorSetting": { "language": "markdown", "editOnDblClick": true, "completionSupport": false }, "colWidth": 12, "editorMode": "ace/mode/markdown", "fontSize": 9, "editorHide": false, "results": {}, "enabled": true }, "settings": { "params": {}, "forms": {} }, "results": { "code": "SUCCESS", "msg": [ { "type": "HTML", "data": "
\n

This is markdown test

\n\n
" } ] }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597133766113_507090317", "id": "paragraph_1597101740623_82179823", "dateCreated": "Aug 11, 2020 8:16:06 AM", "dateStarted": "Aug 11, 2020 8:24:38 AM", "dateFinished": "Aug 11, 2020 8:24:38 AM", "status": "FINISHED" }, { "title": "Paragraph inserted", "text": "%md\n# markdown cell number 2 ", "user": "anonymous", "dateUpdated": "Aug 11, 2020 8:24:32 AM", "config": {}, "settings": { "params": {}, "forms": {} }, "results": { "code": "SUCCESS", "msg": [ { "type": "HTML", "data": "
\n

markdown cell number 2

\n\n
" } ] }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597134223413_576247989", "id": "paragraph_1597134223413_576247989", "dateCreated": "Aug 11, 2020 8:23:43 AM", "dateStarted": "Aug 11, 2020 8:24:32 AM", "dateFinished": "Aug 11, 2020 8:24:32 AM", "status": "FINISHED" } ] } ``` 3. **Add a Notebook →** returns new notebook id ``` POST api/notebooks/note REQUEST BODY {"name": "Demo Notebook"} // new name RESPONSE BODY { "status": "OK", "message": "", "body": "2FG6FWGY5" //New Notebook ID } ``` 4. **Rename a Notebook →** returns acknowledgement ``` PUT api/notebooks/note/rename REQUEST BODY { "noteId": "2FG6FWGY5", // notebook id to be renamed "name":"Demo 1", // new name } RESPONSE BODY { "status": "OK", "message": "" } ``` 5. **Clone a Notebook →** returns new notebook id ``` POST api/notebooks/note/clone REQUEST BODY { "noteId": "2FG6FWGY5", // notebook id to be cloned "name":"Demo 1_copy", // new name for cloned notebook } RESPONSE BODY { "status": "OK", "message": "", "body": "2FFAG7HAQ" } ``` 6. **Delete a Notebook →** returns acknowledgement ``` DELETE api/notebooks/note/{noteid} RESPONSE BODY { "status": "OK", "message": "" } ``` 7. **Import a Notebook →** returns new notebooks Id ``` POST api/notebooks/note/import REQUEST BODY // { noteObj: {notebooks as json} } { "noteObj": { "angularObjects": {}, "config": { "isZeppelinNotebookCronEnable": false }, "defaultInterpreterGroup": "md", "id": "2FH5EF6QF", "info": {}, "name": "test 1", "noteForms": {}, "noteParams": {}, "paragraphs": [{ "apps": [], "config": { "colWidth": 12, "editorHide": false, "editorMode": "ace/mode/markdown", "editorSetting": { "completionSupport": false, "editOnDblClick": true, "language": "markdown" }, "enabled": true, "fontSize": 9, "results": {}, "tableHide": true }, "dateCreated": "2020-08-10 23:22:20.623", "dateFinished": "2020-08-11 08:15:21.175", "dateStarted": "2020-08-11 08:15:21.150", "dateUpdated": "2020-08-11 08:15:21.140", "id": "paragraph_1597101740623_82179823", "jobName": "paragraph_1597101740623_82179823", "progressUpdateIntervalMs": 500, "results": { "code": "SUCCESS", "msg": [{ "data": "
\n

This is markdown test

\n\n
", "type": "HTML" }] }, "runtimeInfos": {}, "settings": { "forms": {}, "params": {} }, "status": "FINISHED", "text": "# This is markdown test", "user": "anonymous" }], "version": "0.9.0-SNAPSHOT" } } RESPONSE BODY { "status": "OK", "message": "", "body": "2FF38BHBY" //new notebook id } ``` 8. **Export a Notebook →** Returns a notebooks object ``` GET api/notebooks/note/export/{noteid} RESPONSE BODY // A notebook object { "paragraphs": [ { "text": "# This is markdown test", "user": "anonymous", "dateUpdated": "2020-08-11 17:08:24.063", "config": { "tableHide": true, "editorSetting": { "completionSupport": false, "editOnDblClick": true, "language": "markdown" }, "colWidth": 12.0, "editorMode": "ace/mode/markdown", "editorHide": false, "fontSize": 9.0, "results": {}, "enabled": true }, "settings": { "params": {}, "forms": {} }, "results": { "code": "SUCCESS", "msg": [ { "type": "HTML", "data": "
\n

This is markdown test

\n\n
" } ] }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597165704063_563073184", "id": "paragraph_1597101740623_82179823", "dateCreated": "2020-08-11 17:08:24.063", "status": "READY" } ], "name": "test 1", "id": "2FF38BHBY", "defaultInterpreterGroup": "spark", "version": "0.9.0-SNAPSHOT", "noteParams": {}, "noteForms": {}, "angularObjects": {}, "config": { "isZeppelinNotebookCronEnable": false }, "info": {} } ``` ## Paragraph APIs 1. **Update and Run a Paragraph →** returns the updated paragraph Does the following backend tasks: 1. Updates a paragraph (with new input) 2. Runs it 3. Fetches the paragraph (with updated input and executed result output) ``` POST api/notebooks/paragraph/update/run REQUEST BODY { "noteId": "2FF38BHBY", // notebook id "paragraphId": "paragraph_1597101740623_82179823", // para id "paragraphInput": "%md\n# This is markdown test 2" // para inp } RESPONSE BODY { "text": "%md\n# This is markdown test 2", "user": "anonymous", "dateUpdated": "Aug 11, 2020 5:35:01 PM", "config": { "tableHide": true, "editorSetting": { "completionSupport": false, "editOnDblClick": true, "language": "markdown" }, "colWidth": 12, "editorMode": "ace/mode/markdown", "editorHide": false, "fontSize": 9, "results": {}, "enabled": true }, "settings": { "params": {}, "forms": {} }, "results": { "code": "SUCCESS", "msg": [ { "type": "HTML", "data": "
\n

This is markdown test 2

\n\n
" } ] }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597165704063_563073184", "id": "paragraph_1597101740623_82179823", "dateCreated": "Aug 11, 2020 5:08:24 PM", "dateStarted": "Aug 11, 2020 5:35:01 PM", "dateFinished": "Aug 11, 2020 5:35:01 PM", "status": "FINISHED" } ``` 2. **Update a Paragraph →** returns the updated paragraph Does the following backend tasks: 1. Updates a paragraph (with new input) 2. Fetches the paragraph (with updated input and old output) NOTE: This API call doesn’t execute the paragraph input, should be used to save a partially written code ``` PUT api/notebooks/paragraph/ REQUEST BODY { "noteId": "2FF3GW3H8", // notebook id "paragraphId": "paragraph_1596519508360_932236116", // para id "paragraphInput": "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* I was not present in previous input" // new input } RESPONSE BODY { "text": "%md \n\n### Hi Everyone\n* Here's a demo on **OpenSearch Dashboards Notebooks**\n* I was present in previous input", "user": "anonymous", "dateUpdated": "Aug 11, 2020 5:52:14 PM", "config": {}, "settings": { "params": {}, "forms": {} }, "results": { "code": "SUCCESS", "msg": [{ "type": "HTML", // old result "data": "
\n

Hi Everyone

\n\n\n
" }] }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597104141269_874537409", "id": "paragraph_1596519508360_932236116", "dateCreated": "Aug 11, 2020 12:02:21 AM", "dateStarted": "Aug 11, 2020 5:51:43 PM", "dateFinished": "Aug 11, 2020 5:51:43 PM", "status": "FINISHED" } ``` 3. **Add a new paragraph →** returns newly created paragraph Does the following backend tasks: 1. Adds new a paragraph 2. Fetches the newly created paragraph ``` POST api/notebooks/paragraph/ REQUEST BODY { "noteId": "2FF3GW3H8", // notebook id "paragraphIndex": 1, // index to create a new para "paragraphInput": "%opensearch\n" // input to be provided in the new para "inputType": "CODE" // a paragraph can be of type CODE or VISUALIZATION } RESPONSE BODY { "title": "Paragraph inserted", "text": "%opensearch\n", "user": "anonymous", "dateUpdated": "Aug 11, 2020 5:56:23 PM", "config": {}, "settings": { "params": {}, "forms": {} }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597168583538_1357513873", "id": "paragraph_1597168583538_1357513873", "dateCreated": "Aug 11, 2020 5:56:23 PM", "status": "READY" } ``` 4. **Delete a paragraph →** returns list of paragraphs ``` DELETE api/notebooks/paragraph/{noteId}/{paragraphId} RESPONSE BODY // list of Paragraphs { "paragraphs": [{ "text": "%md\n# This is markdown test 2", "user": "anonymous", "dateUpdated": "Aug 11, 2020 6:55:07 PM", "config": { "tableHide": true, "editorSetting": { "completionSupport": false, "editOnDblClick": true, "language": "markdown" }, "colWidth": 12, "editorMode": "ace/mode/markdown", "editorHide": false, "fontSize": 9, "results": {}, "enabled": true }, "settings": { "params": {}, "forms": {} }, "results": { "code": "SUCCESS", "msg": [{ "type": "HTML", "data": "
\n

This is markdown test 2

\n\n
" }] }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597165704063_563073184", "id": "paragraph_1597101740623_82179823", "dateCreated": "Aug 11, 2020 5:08:24 PM", "dateStarted": "Aug 11, 2020 6:55:07 PM", "dateFinished": "Aug 11, 2020 6:55:07 PM", "status": "FINISHED" }, { "title": "Paragraph inserted", "text": "%opensearch\n", "user": "anonymous", "dateUpdated": "Aug 11, 2020 6:55:07 PM", "config": {}, "settings": { "params": {}, "forms": {} }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597172107715_362327829", "id": "paragraph_1597172107715_362327829", "dateCreated": "Aug 11, 2020 6:55:07 PM", "status": "READY" }] } ``` 5. **Clear outputs of all paragraphs →** returns list of paragraphs (with empty outputs) ``` PUT api/notebooks/paragraph/clear REQUEST BODY {"noteId":"2FF38BHBY"} // notebook id to clear all paras RESPONSE BODY // list of Paragraphs { "paragraphs": [{ "text": "%md\n# This is markdown test 2", "user": "anonymous", "dateUpdated": "Aug 11, 2020 6:55:07 PM", "config": { "tableHide": true, "editorSetting": { "completionSupport": false, "editOnDblClick": true, "language": "markdown" }, "colWidth": 12, "editorMode": "ace/mode/markdown", "editorHide": false, "fontSize": 9, "results": {}, "enabled": true }, "settings": { "params": {}, "forms": {} }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597165704063_563073184", "id": "paragraph_1597101740623_82179823", "dateCreated": "Aug 11, 2020 5:08:24 PM", "dateStarted": "Aug 11, 2020 6:55:07 PM", "dateFinished": "Aug 11, 2020 6:55:07 PM", "status": "FINISHED" }, { "title": "Paragraph inserted", "text": "%md\n\n# Output is empty\n", "user": "anonymous", "dateUpdated": "Aug 11, 2020 7:17:31 PM", "config": {}, "settings": { "params": {}, "forms": {} }, "apps": [], "runtimeInfos": {}, "progressUpdateIntervalMs": 500, "jobName": "paragraph_1597172107715_362327829", "id": "paragraph_1597172107715_362327829", "dateCreated": "Aug 11, 2020 6:55:07 PM", "dateStarted": "Aug 11, 2020 7:17:31 PM", "dateFinished": "Aug 11, 2020 7:17:31 PM", "status": "FINISHED" }] } ``` ## **Future Work** ### **Short Term** 1. **Notes APIs** 1. Run notebook → runs all the paragraphs and returns the updated list of paragraphs 2. Save notebook → updates all the paragraphs and returns the updated list of paragraphs 2. **Paragraph APIs** 1. Run a paragraph → runs the paragraph with pre-exisiting input code and returns the updated paragraph (with executed result) 2. Refresh a paragraph → runs the paragraph with pre-exisiting input code at certain intervals and returns the updated paragraph (with executed result) ### **Long Term** 1. Checkpoint notebook → saves all the paragraphs and returns acknowledgement 2. Extend endpoints like refresh, run, save and checkpoint to be asynchronous ## References: 1. Zeppelin APIs : http://zeppelin.apache.org/docs/0.9.0/usage/rest_api/notebook.html 2. More About Zeppelin: https://zeppelin.apache.org/docs/0.9.0/