- (JSON-in) All methods pass their argument in a json hash in the HTTP request body.
- (JSON-out) All methods return a json hash in the HTTP response body.
- GET is used for queries.
- POST is used for modifiers.
- Paths are not REST-ful.
A cluster is the umbrella over a multi Language-Test-Framework (LTF) practice: it offers 2..5 LTFs, holding one ordinary Group per LTF (its children). A cluster is never joined directly; a joiner joins one of its child groups.
-
description
- Creates a cluster from the given
manifestand returns its id. The manifest holds the group-wideexerciseand anltfsarray (2..5 per-LTF group manifests). For each ltf a child group is created, carrying acluster_idback-pointer, and the cluster references the children.
- Creates a cluster from the given
-
parameters
Name Type Description manifestHashwith exercise:Stringandltfs:Array[Hash], the 2..5 per LTF group manifests (as built by creator). -
returns
- the
idof the created cluster. - status 400 if
ltfsdoes not hold 2..5 entries.
- the
-
example
$ curl \ --data '{"manifest":{"exercise":"Tennis","ltfs":[...]}}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/cluster_create | jq .
{ "cluster_create": "dFg8Us" }
-
description
- Gets the manifest of the cluster with the given
id: itsexerciseand itschildren(one per LTF, each{ltf_display_name, group_id}).
- Gets the manifest of the cluster with the given
-
parameters
Name Type Description idStringThe cluster id. -
returns
- the manifest of the cluster with the given
id.
- the manifest of the cluster with the given
-
example
$ curl \ --data '{"id":"dFg8Us"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/cluster_manifest | jq .
{ "cluster_manifest": { "id": "dFg8Us", "exercise": "Tennis", "children": [ { "ltf_display_name": "Python, unittest", "group_id": "g1AbCd" }, { "ltf_display_name": "Ruby, MiniTest", "group_id": "g2EfGh" } ] } }
-
description
- Determines if a cluster with the given
idexists.
- Determines if a cluster with the given
-
parameters
Name Type Description idStringThe cluster id. -
returns
trueif a cluster with the givenidexists, otherwisefalse.
-
example
$ curl \ --data '{"id":"dFg8Us"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/cluster_exists? | jq .
{ "cluster_exists?": true }
A group is a shared practice for a single Language-Test-Framework: joiners join it, each allocated a distinct avatar (Lion, Salmon, Bee, etc) and their own Kata of the group's exercise. A group holds up to 64 katas, one per avatar. In a Cluster a group is one of the children (one per LTF).
-
description
- Creates a new group from the given
manifestand returns its id.
Seegroup_manifestbelow for amanifestoverview.
See here for more detailedmanifestinformation.
- Creates a new group from the given
-
parameters
Name Type Description manifestHashcreated by creator from languages-start-points and exercises-start-points or custom-start-points. -
returns
- the
idof the created group.
- the
-
example
$ curl \ --data '{"manifest":...}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/group_create | jq .
{ "group_create": "dFg8Us" }
-
description
- Gets the manifest used to create the group with the given
id.
- Gets the manifest used to create the group with the given
-
parameters
Name Type Description idStringThe group id. -
returns
- the manifest of the group with the given
id.
- the manifest of the group with the given
-
example
$ curl \ --data '{"id":"dFg8Us"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/group_manifest | jq .
{ "group_manifest": { "display_name": "Bash, bats", "image_name": "cyberdojofoundation/bash_bats:53d0c9c", "filename_extension": [ ".sh" ], "tab_size": 4, "visible_files": { "test_hiker.sh": { "content": "..." }, "bats_help.txt": { "content": "..." }, "hiker.sh": { "content": "..." }, "cyber-dojo.sh": { "content": "..." }, "readme.txt": { "content": "..." } }, "exercise": "LCD Digits", "version": 1, "created": [2020,10,19,12,51,32,991192], "id": "REf1t8", "highlight_filenames": [], "max_seconds": 10, "progress_regexs": [] } }
-
description
- Determines if a group with the given
idexists.
- Determines if a group with the given
-
parameters
Name Type Description idStringThe group id. -
returns
trueif a group with the givenidexists, otherwisefalse.
-
example
$ curl \ --data '{"id":"dFg8Us"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/group_exists? | jq .
{ "group_exists?": true }
-
description
- Creates a new kata in the group with the given
idand returns the kata's id.
- Creates a new kata in the group with the given
-
parameters
Name Type Description idStringThe group id. indexesArray[int](optional). The candidate avatar indexes (from 0..63) in preference order. The first index not already taken in the group is allocated. Defaults to a shuffled 0..63. Pass a custom order to influence which avatar a joiner gets. For example, in a cluster, list the avatars not yet used elsewhere in the cluster first, so avatars stay distinct across the cluster's groups. -
returns
- the
idof the created kata, ornullif the group is already full.
- the
-
example
$ curl \ --data '{"id":"dFg8Us"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/group_join | jq .
{ "group_join": "a8gVRN" }
-
description
- Returns the kata-id and kata-events-summary keyed against the kata's avatar-index (0-63) for the katas that have joined a group.
-
parameters
Name Type Description idStringThe group's idor theidof any kata in the group. -
returns
- a Hash.
-
example
$ curl \ --data '{"id":"dFg8Us"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/group_joined | jq .
{ "group_joined": { "7": { "id": "a8gVRN", "events": [...] }, "29": { "id": "gUNjUV", "events": [...] }, ... } }
-
description
- Creates a new group whose starting files are a copy of the files in the kata with
the given
idat the givenindex. The new group is not a fork in the git sense; that is, it is not a 'deep' copy, the history of commits (one per test event) that exist in the kata being forked are not copied.
- Creates a new group whose starting files are a copy of the files in the kata with
the given
-
parameters
Name Type Description idStringThe id of the kata being forked. indexintThe event index to fork from. -
returns
- the
idof the created group.
- the
-
example
$ curl \ --data '{"id":"dFg8Us", "index":23}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/group_fork | jq .
{ "group_fork": "a8gVRN" }
A kata is one participant's practice: created from a manifest (an exercise for a single Language-Test-Framework), it records every event as its own git commit - the create, each file create/delete/rename/edit, and each test run with its traffic-light colour (red, amber, green). Each avatar in a Group is a kata.
-
description
- Creates a new kata from the given
manifestand returns its id.
Seekata_manifestbelow for amanifestoverview.
See here for more detailedmanifestinformation.
- Creates a new kata from the given
-
parameters
Name Type Description manifestHashcreated by creator from languages-start-points and exercises-start-points (or custom-start-points). -
returns
- the
idof the created kata.
- the
-
example
$ curl \ --data '{"manifest":...}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/kata_create | jq .
{ "kata_create": "dFg8Us" }
-
description
- Gets the manifest used to create the kata exercise with the given
id.
- Gets the manifest used to create the kata exercise with the given
-
parameters
Name Type Description idStringThe kata id. -
returns
- the manifest of the kata with the given
id.
- the manifest of the kata with the given
-
example
$ curl \ --data '{"id":"4ScKVJ"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/kata_manifest | jq .
{ "kata_manifest": { "display_name": "Bash, bats", "image_name": "cyberdojofoundation/bash_bats:53d0c9c", "filename_extension": [ ".sh" ], "tab_size": 4, "visible_files": { "test_hiker.sh": { "content": "..." }, "bats_help.txt": { "content": "..." }, "hiker.sh": { "content": "..." }, "cyber-dojo.sh": { "content": "..." }, "readme.txt": { "content": "..." } }, "exercise": "LCD Digits", "version": 1, "created": [2020,10,19,12,52,46,396907], "group_id": "REf1t8", "group_index": 44, "id": "4ScKVJ", "highlight_filenames": [], "max_seconds": 10, "progress_regexs": [] } }
-
description
- Determines if a kata exercise with the given
idexists.
- Determines if a kata exercise with the given
-
parameters
Name Type Description idStringThe kata id. -
returns
trueif a kata with the givenidexists, otherwisefalse.
-
example
$ curl \ --data '{"id":"4ScKVJ"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/kata_exists? | jq .
{ "kata_exists?": false }
-
description
- Gets the summary of all current events for the kata with the given
id.
- Gets the summary of all current events for the kata with the given
-
parameters
Name Type Description idStringThe kata id. -
returns
- an Array holding the events summary of the kata with the given
id. Each event carries three positional indexes, computed on read (the event-write POSTs do not return them):index- the event's absolute position, soevents[index].index == index.major_index- the number of red/amber/green traffic-lights up to and including this event (thecreatedevent is0); a traffic-light is always atmajor_indexwithminor_index0.minor_index-0on a traffic-light; incremented by each inter-test file event (create/delete/rename/edit) since the previous traffic-light.
- an Array holding the events summary of the kata with the given
-
example
$ curl \ --data '{"id":"4ScKVJ"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/kata_events | jq .
{ "kata_events": [ { "index": 0, "major_index": 0, "minor_index": 0, "time": [2020,10,19,12,52,46,396907], "colour": "create", "event": "created", "diff_added_count": 0, "diff_deleted_count": 0 }, { "index": 1, "major_index": 1, "minor_index": 0, "time": [2020,10,19,12,52,54,772809], "colour": "red", "duration": 0.491393, "predicted": "none", "diff_added_count": 4, "diff_deleted_count": 1, "laptop_id": "02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f", "tab_seq": 1 }, { "index": 2, "major_index": 2, "minor_index": 0, "time": [2020,10,19,12,52,58,547002], "colour": "amber", "duration": 0.426736, "predicted": "none", "diff_added_count": 2, "diff_deleted_count": 0, "laptop_id": "02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f", "tab_seq": 2 }, { "index": 3, "major_index": 3, "minor_index": 0, "time": [2020,10,19,12,53,3,256202], "colour": "green", "duration": 0.438522, "predicted": "none", "diff_added_count": 3, "diff_deleted_count": 2, "laptop_id": "02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f", "tab_seq": 3 } ] }
-
description
- Gets the full details for the kata event whose kata has the given
idwhose event has the givenindex.
- Gets the full details for the kata event whose kata has the given
-
parameters
Name Type Description idStringThe kata id. indexintNegative values count backwards, -1 is the last index. -
returns
- the event with the given
idandindex.
- the event with the given
-
example
$ curl \ --data '{"id":"4ScKVJ","index":2}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/kata_event | jq .
{ "kata_event": { "files": { "test_hiker.sh": { "content": "..." }, "bats_help.txt": { "content": "..." }, "hiker.sh": { "content": "..." }, "cyber-dojo.sh": { "content": "..." }, "readme.txt": { "content": "..." } }, "stdout": { "content": "...", "truncated": false }, "stderr": { "content": "...", "truncated": false }, "status": "1", "index": 2, "major_index": 2, "minor_index": 0, "time": [2020,10,19,12,52,58,547002], "colour": "amber", "duration": 0.426736, "predicted": "none", "diff_added_count": 2, "diff_deleted_count": 0, "laptop_id": "02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f", "tab_seq": 2 } }
-
description
- Gets the full details for the kata events with the given
idsandindexes. A Batch-Method for kata_event(id,index).
- Gets the full details for the kata events with the given
-
parameters
Name Type Description idsArray[String]The kata ids. indexArray[int]The corresponding event indexes. -
returns
- the events with the given
idsandindexes.
- the events with the given
-
example
$ curl \ --data '{"ids":["4ScKVJ","De87Aa"],"indexes":[23,45]}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/katas_events | jq .
{ "katas_events": { "4ScKVJ": { "23": { "files": { ... }, "stdout": { ... } ... } }, "De87Aa": { "45": { "files": { ... }, "stdout": { ... } ... } } } }
-
description
- Returns a gzipped tar archive of the kata's git repository, base64-encoded.
-
parameters
Name Type Description idStringThe kata id. -
returns
- an Array of two elements: the suggested filename (
String) and the base64-encoded tgz content (String).
- an Array of two elements: the suggested filename (
-
example
$ curl \ --data '{"id":"4ScKVJ"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/kata_download | jq .
{ "kata_download": [ "cyber-dojo-2026-4-6-4ScKVJ.tgz", "H4sIAAAAAAAAA+..." ] }
-
description
- Records a new empty file being created in the browser. If any existing file has been edited since the last save, that edit is recorded first as a
file_editevent.
- Records a new empty file being created in the browser. If any existing file has been edited since the last save, that edit is recorded first as a
-
parameters
Name Type Description idStringThe kata id. filesHashThe current files (the new filenameis not yet present).filenameStringThe name of the file being created. laptop_idStringSee laptop_id. tab_seqintSee tab_seq. -
returns
- nothing meaningful (a 200 ack); the event is recorded - read it back via kata_events.
-
example
$ curl \ --data '{"id":"4ScKVJ","files":{...},"filename":"utils.sh","laptop_id":"02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f","tab_seq":1}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/kata_file_create
-
description
- Records a file being deleted in the browser. If any existing file has been edited since the last save, that edit is recorded first as a
file_editevent.
- Records a file being deleted in the browser. If any existing file has been edited since the last save, that edit is recorded first as a
-
parameters
Name Type Description idStringThe kata id. filesHashThe current files (the filenameto delete is still present).filenameStringThe name of the file being deleted. laptop_idStringSee laptop_id. tab_seqintSee tab_seq. -
returns
- nothing meaningful (a 200 ack); the event is recorded - read it back via kata_events.
-
example
$ curl \ --data '{"id":"4ScKVJ","files":{...},"filename":"utils.sh","laptop_id":"02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f","tab_seq":2}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/kata_file_delete
-
description
- Records a file being renamed in the browser. If any existing file has been edited since the last save, that edit is recorded first as a
file_editevent.
- Records a file being renamed in the browser. If any existing file has been edited since the last save, that edit is recorded first as a
-
parameters
Name Type Description idStringThe kata id. filesHashThe current files ( old_filenameis present;new_filenameis not yet present).old_filenameStringThe current name of the file. new_filenameStringThe new name of the file. laptop_idStringSee laptop_id. tab_seqintSee tab_seq. -
returns
- nothing meaningful (a 200 ack); the event is recorded - read it back via kata_events.
-
example
$ curl \ --data '{"id":"4ScKVJ","files":{...},"old_filename":"utils.sh","new_filename":"helpers.sh","laptop_id":"02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f","tab_seq":3}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/kata_file_rename
-
description
- Records a file edit event if any file content has changed since the last save. If no file has changed, no event is recorded.
-
parameters
Name Type Description idStringThe kata id. filesHashThe current files. laptop_idStringSee laptop_id. tab_seqintSee tab_seq. -
returns
- nothing meaningful (a 200 ack); the file_edit event, if any, is recorded - read it back via kata_events.
-
example
$ curl \ --data '{"id":"4ScKVJ","files":{...},"laptop_id":"02cfdffb5c0c31221b837a153d1108e6cd19fd6cef11db27c8457a1e63caf46f","tab_seq":4}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/kata_file_edit
-
description
- Record a test event with no prediction.
-
parameters
Name Type Description idStringThe kata id. filesHashThe files which created stdout,stderr,statusin the same format as kata_eventstdoutHashThe stdout produced from files, in the same format as kata_eventstderrHashThe stderr produced from files, in the same format as kata_eventstatusStringThe status produced from files, in the same format as kata_eventsummaryHashExtra event data to store, eg duration,time,colourlaptop_idStringSee laptop_id. tab_seqintSee tab_seq.
- description
- Record a test event with a correct prediction.
- description
- Record a test event with an incorrect prediction.
- description
- Revert back to a previous traffic-light.
- description
- Checkout a traffic-light from a different avatar.
- description
- Get a theme (dark/light) or colour (on/off) or prediction (on/off) option.
- description
- Set a theme (dark/light) or colour (on/off) or prediction (on/off) option.
-
description
- Creates a new kata whose starting files are a copy of the files in the kata with
the given
idat the givenindex. The new kata is not a fork in the git sense; that is, it is not a 'deep' copy, the history of commits (one per test event) that exist in the kata being forked are not copied.
- Creates a new kata whose starting files are a copy of the files in the kata with
the given
-
parameters
Name Type Description idStringindexint -
returns
- the
idof the created kata.
- the
-
example
$ curl \ --data '{"id":"dFg8Us", "index":23}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request POST \ https://${DOMAIN}:${PORT}/kata_fork | jq .
{ "kata_fork": "a8gVRN" }
Find the full Cluster/Group/Kata information of any id.
-
description
- Returns the chain of ids from the given
idup to its topmost containing entity, ordered bottom-to-top as[{type,id}, ...]wheretypeiskata,grouporcluster. The first entry is the given id; the last entry's id is the topmost. Lets a caller resolve any id up to the practice it belongs to (eg a kata up to its cluster).
- Returns the chain of ids from the given
-
parameters
Name Type Description idStringA kata, group or cluster id. -
returns
- the id chain. A solo kata returns just itself; a kata in a cluster returns its kata, then group, then cluster.
-
example
$ curl \ --data '{"id":"5rTJv5"}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/id_chain | jq .
{ "id_chain": [ { "type": "kata", "id": "5rTJv5" }, { "type": "group", "id": "g1AbCd" }, { "type": "cluster", "id": "dFg8Us" } ] }
Compare a Kata's files between two event indexes.
-
description
- A diff of two sets of files (designated with
was_indexandnow_index) from the kata with the givenid. Every line of every file is returned - not just the changed lines with a few unchanged lines either side as a normalgit diffwould give. Unchanged files and files renamed with identical content are also included.
- A diff of two sets of files (designated with
-
parameters
Name Type Description idStringThe kata id. was_indexIntegerThe event index of the first set of files. now_indexIntegerThe event index of the second set of files. -
returns
- an Array of Hashes, one per file. Each Hash has the following keys:
"type"- one of"created","deleted","renamed","changed","unchanged"."old_filename"- the filename atwas_index, ornullif"type"is"created"."new_filename"- the filename atnow_index, ornullif"type"is"deleted"."lines"- an Array of Hashes, each with"type"("added","deleted","same", or"section")."line_counts"- a Hash with"added","deleted", and"same"counts.
- an Array of Hashes, one per file. Each Hash has the following keys:
-
example
$ curl \ --data '{"id":"4ScKVJ","was_index":3,"now_index":4}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/diff_lines | jq .
{ "diff_lines": [ { "type": "changed", "old_filename": "hiker.py", "new_filename": "hiker.py", "lines": [ { "type": "same", "line": "class Hiker:", "number": 1 }, { "type": "section", "index": 0 }, { "type": "deleted", "line": " pass", "number": 2 }, { "type": "added", "line": " def answer(self):", "number": 2 }, { "type": "added", "line": " return 42", "number": 3 } ], "line_counts": { "added": 2, "deleted": 1, "same": 1 } }, ... ] }
-
description
- The same as
diff_linesexcept the returned Hashes do not include the"lines"key.
- The same as
-
parameters
Name Type Description idStringThe kata id. was_indexIntegerThe event index of the first set of files. now_indexIntegerThe event index of the second set of files. -
returns
- an Array of Hashes with
"type","old_filename","new_filename", and"line_counts"(no"lines").
- an Array of Hashes with
-
example
$ curl \ --data '{"id":"4ScKVJ","was_index":3,"now_index":4}' \ --fail \ --header 'Content-type: application/json' \ --silent \ --request GET \ https://${DOMAIN}:${PORT}/diff_summary | jq .
{ "diff_summary": [ { "type": "changed", "old_filename": "hiker.py", "new_filename": "hiker.py", "line_counts": { "added": 2, "deleted": 1, "same": 1 } }, ... ] }
Operational health checks, plus the git sha of the running image.
- description
- Liveness probe - is the service alive?
- parameters
- none
- result
- true
- example
$ curl --fail --silent --request GET https://${DOMAIN}:${PORT}/alive? | jq .
{ "alive?": true }
- description
- Readiness probe - is the service ready to handle requests?
- parameters
- none
- result
- true when the service is ready
- false when the service is not ready
- example
$ curl --fail --silent --request GET https://${DOMAIN}:${PORT}/ready? | jq .
{ "ready?": false }
- description
- The git commit sha used to create the Docker image.
- parameters
- none
- result
- the 40 character commit sha string.
- example
$ curl --fail --silent --request GET https://${DOMAIN}:${PORT}/sha | jq .
{ "sha": "41d7e6068ab75716e4c7b9262a3a44323b4d1448" }
The 64-char lowercase-hex id of the writer, used by the browser's read-side poll
for unintended "mobbing" detection. It is two 32-char halves: the first 32 identify the browser
(laptop) profile, the last 32 identify the writing tab (its tab_id), so the poll
can tell one tab from another as well as one laptop from another. (A non-JS client
that sends no tab_id falls back to its plain 64-char browser cookie.) The saver
stamps a valid laptop_id onto the committed event verbatim; a value that is not
64 lowercase-hex characters is not trusted and is not stored, so the event reads as
having an unknown writer.
Accepted by kata_file_create, kata_file_delete, kata_file_rename,
kata_file_edit, kata_ran_tests, kata_predicted_right, kata_predicted_wrong,
kata_reverted and kata_checked_out.
The writing tab's own monotonic event counter, minted in the browser and counting
every event the tab fires (its first event is 1, the next 2, and so on).
Together with laptop_id it forms the (laptop_id, tab_seq) idempotency key: the
saver stamps it onto the committed event, and a later write carrying a
(laptop_id, tab_seq) that is already committed is a no-op, so a redelivered write
is never committed twice.
Accepted by kata_file_create, kata_file_delete, kata_file_rename,
kata_file_edit, kata_ran_tests, kata_predicted_right, kata_predicted_wrong,
kata_reverted and kata_checked_out.
- All methods pass their argument in a json hash in the http request body.
- If there are no arguments you can use
''(which is the default forcurl --data) instead of'{}'.
- All methods return a json hash in the http response body.
- If the method does not raise, a string key equals the method's name. eg
$ curl --silent -X GET https://${DOMAIN}:${PORT}/ready? | jq .
{ "ready?": true } - If the method raises an exception, a string key equals
"exception", with a json-hash as its value. eg$ curl --data 'not-json-hash' --silent -X GET https://${DOMAIN}:${PORT}/run | jq
{ "exception": { "path": "/run", "body": "not-json-hash", "class": "SaverService", "message": "...", "backtrace": [ ... "/usr/bin/rackup:23:in `<main>'" ] } }