Webhooks
Workspaces

A webhook message is an HTTP POST request sent from Sphere Engine to the client's webhook endpoint. Enclosed within the request body is valid JSON data structured uniformly across all Sphere Engine components. The following events are activated by specific actions within the Container module workspaces, initiating the dispatch of a webhook:

Event name Trigger Comments
workspace.scenario.finished Scenario execution has finished Scenario execution must finish without interruption (e.g., being killed by the end-user) for the webhook to be sent
workspace.scenario.custom Call to se_utils using CLI or Python -

Webhook message specification

Webhooks concerning workspace events are consistently transmitted as an array, enabling reception of multiple messages within a single HTTP request. The following outlines the specification for an individual element within this array.

A single request can carry up to 10 webhook messages.

Message core

Name Type Description
id string Unique identifier of the webhook message
origin string

Sphere Engine system identifier that can take the following values:

  • secow - Containers module Workspaces
timestamp integer The Unix timestamp generated when the message is created
type object Information about the type of the webhook event. It can take the following values:
- workspace.scenario.finished - for a scenario execution event
- workspace.scenario.custom - for a custom event
payload object The event details

The structure of the payload object for the workspace.scenario.finished event type.

Name Type Description
started_at string date and time at which the scenario execution has began [yyyy-mm-dd hh:mm:ss TZD]; always in UTC timezone
workspace object workspace details
workspace.id string workspace id
project object project details
project.id string project id
project.name string project name
result object result details
result.status object result status
result.status.code integer result status code (see section: submission status)
result.status.name string result status name
result.score float score
result.time float execution time [seconds]
scenario string executed scenario name
stages object details of the stages;
null if stage results are not available
stages.init object initialization stage details
stages.init.skipped boolean whether the stage has been skipped
stages.init.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.init.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.init.time integer stage execution time [seconds]
stages.init.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.init.status_changed_to.code integer status code (see section: submission status)
stages.init.status_changed_to.name string status name
stages.init.status_changed_to.desc string or null description of the reason for the status change;
null if there is no description
stages.build object build stage details
stages.build.skipped boolean whether the stage has been skipped
stages.build.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.build.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.build.time integer stage execution time [seconds]
stages.build.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.build.status_changed_to.code integer status code (see section: submission status)
stages.build.status_changed_to.name string status name
stages.build.status_changed_to.desc string or null description of the reason for the status change;
null if there is no description
stages.run object run stage details
stages.run.skipped boolean whether the stage has been skipped
stages.run.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.run.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.run.time integer stage execution time [seconds]
stages.run.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.run.status_changed_to.code integer status code (see section: submission status)
stages.run.status_changed_to.name string status name
stages.run.status_changed_to.desc string or null description of the reason for the status change;
null if there is no description
stages.test object test stage details
stages.test.skipped boolean whether the stage has been skipped
stages.test.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.test.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.test.time integer stage execution time [seconds]
stages.test.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.test.status_changed_to.code integer status code (see section: submission status)
stages.test.status_changed_to.name string status name
stages.test.status_changed_to.desc string or null description of the reason for the status change;
null if there is no description
stages.post object post-processing stage details
stages.post.skipped boolean whether the stage has been skipped
stages.post.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.post.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.post.time integer stage execution time [seconds]
stages.post.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.post.status_changed_to.code integer status code (see section: submission status)
stages.post.status_changed_to.name string status name
stages.post.status_changed_to.desc string or null description of the reason for the status change;
null if there is no description
streams object details of the streams
streams.auxdata object or null auxdata stream details;
null if the stream is not available;
the stream content is generated from directories defined in the scenario configuration; for more information about auxdata, see Extracting custom files from a workspace
streams.auxdata.size integer size of auxiliary data stream [bytes]
streams.auxdata.uri integer link to the file with auxiliary data generated by the scenario
streams.tests_report object or null details of the tests report stream;
null if the stream is not available;
for more information, see Tests report format
streams.tests_report.size integer size of final tests report [bytes]
streams.tests_report.uri integer link to the file with final tests report generated by the scenario
streams.stage_init_output object or null stage init output info;
null if the stream is not available
streams.stage_init_output.size integer size of the init stage's output [bytes]
streams.stage_init_output.uri integer link to the file with the init stage's output
streams.stage_init_error object or null stage init error info;
null if the stream is not available
streams.stage_init_error.size integer size of the init stage's error [bytes]
streams.stage_init_error.uri integer link to the file with the init stage's error
streams.stage_build_output object or null stage build output info;
null if the stream is not available
streams.stage_build_output.size integer size of the build stage's output [bytes]
streams.stage_build_output.uri integer link to the file with the build stage's output
streams.stage_build_error object or null stage build error info;
null if the stream is not available
streams.stage_build_error.size integer size of the build stage's error [bytes]
streams.stage_build_error.uri integer link to the file with the build stage's error
streams.stage_run_output object or null stage run output info;
null if the stream is not available
streams.stage_run_output.size integer size of the run stage's output [bytes]
streams.stage_run_output.uri integer link to the file with the run stage's output
streams.stage_run_error object or null stage run error info;
null if the stream is not available
streams.stage_run_error.size integer size of the run stage's error [bytes]
streams.stage_run_error.uri integer link to the file with the run stage's error
streams.stage_test_output object or null stage test output info;
null if the stream is not available
streams.stage_test_output.size integer size of the test stage's output [bytes]
streams.stage_test_output.uri integer link to the file with the test stage's output
streams.stage_test_error object or null stage test error info;
null if the stream is not available
streams.stage_test_error.size integer size of the test stage's error [bytes]
streams.stage_test_error.uri integer link to the file with the test stage's error
streams.stage_post_output object or null stage post output info;
null if the stream is not available
streams.stage_post_output.size integer size of the post stage's output [bytes]
streams.stage_post_output.uri integer link to the file with the post stage's output
streams.stage_post_error object or null stage post error info;
null if the stream is not available
streams.stage_post_error.size integer size of the post stage's error [bytes]
streams.stage_post_error.uri integer link to the file with the post stage's error

By default, for the workspace.scenario.finished event, webhook deliveries include only the auxdata and tests_report streams. To personalize the available streams, refer to the options provided for webhooks.

The structure of the payload object for the workspace.scenario.custom event type.

Name Type Description
started_at string date and time at which the scenario execution has began [yyyy-mm-dd hh:mm:ss TZD]; always in UTC timezone
workspace object workspace details
workspace.id string workspace id
project object project details
project.id string project id
project.name string project name
scenario string executed scenario name
stages object details of the stages
stages.init object or null initialization stage details;
null if the stage is not yet available at the time of the webhook transmission
stages.init.skipped boolean whether the stage has been skipped
stages.init.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.init.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.init.time integer stage execution time [seconds]
stages.init.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.init.status_changed_to.code integer status code (see section: submission status)
stages.init.status_changed_to.name string status name
stages.init.status_changed_to.desc string or null description of the reason for the status change
stages.build object or null build stage details;
null if the stage is not yet available at the time of the webhook transmission
stages.build.skipped boolean whether the stage has been skipped
stages.build.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.build.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.build.time integer stage execution time [seconds]
stages.build.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.build.status_changed_to.code integer status code (see section: submission status)
stages.build.status_changed_to.name string status name
stages.build.status_changed_to.desc string or null description of the reason for the status change
stages.run object or null run stage details;
null if the stage is not yet available at the time of the webhook transmission
stages.run.skipped boolean whether the stage has been skipped
stages.run.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.run.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.run.time integer stage execution time [seconds]
stages.run.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.run.status_changed_to.code integer status code (see section: submission status)
stages.run.status_changed_to.name string status name
stages.run.status_changed_to.desc string or null description of the reason for the status change
stages.test object or null test stage details;
null if the stage is not yet available at the time of the webhook transmission
stages.test.skipped boolean whether the stage has been skipped
stages.test.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.test.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.test.time integer stage execution time [seconds]
stages.test.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.test.status_changed_to.code integer status code (see section: submission status)
stages.test.status_changed_to.name string status name
stages.test.status_changed_to.desc string or null description of the reason for the status change
stages.post object or null post-processing stage details;
null if the stage is not yet available at the time of the webhook transmission
stages.post.skipped boolean whether the stage has been skipped
stages.post.exit_code integer or null stage termination exit code;
null if exit code is not available (e.g. stage skipped)
stages.post.signal integer or null interrupt signal for the stage termination;
null if signal is not available (e.g. stage skipped)
stages.post.time integer stage execution time [seconds]
stages.post.status_changed_to object or null details of the execution status change within the stage;
null if status hasn't changed
stages.post.status_changed_to.code integer status code (see section: submission status)
stages.post.status_changed_to.name string status name
stages.post.status_changed_to.desc string or null description of the reason for the status change
streams object details of the streams
streams.auxdata object or null auxdata stream details;
null if the stream is not available;
the stream content is generated from directories defined in the scenario configuration; for more information about auxdata, see Extracting custom files from a workspace
streams.auxdata.size integer size of auxiliary data stream [bytes]
streams.auxdata.uri integer link to the file with auxiliary data generated by the scenario

After a message is sent, streams remain available for download for 24 hours.

Examples

[
  {
    "origin": "secow",
    "id": "4d136f4b-8f3a-4d61-9c0f-9cefce91b549",
    "type": "workspace.scenario.finished",
    "timestamp": 1696420138,
    "payload": {
      "started_at": "2023-10-04 11:48:43 +0000",
      "workspace": {
        "id": "714c7e13fe9c40bd9d47f990317190f1"
      },
      "project": {
        "id": "bb1c27b4aa9e4c7ea74f38c9dd863046",
        "name": "Web React - webhook sample"
      },
      "result": {
        "status": {
          "code": 15,
          "name": "ok"
        },
        "score": 100,
        "time": 11.94
      },
      "scenario": "test",
      "stages": {
        "init": {
          "skipped": true,
          "exit_code": null,
          "signal": null,
          "time": 0,
          "status_changed_to": null
        },
        "build": {
          "skipped": false,
          "exit_code": 0,
          "signal": null,
          "time": 4.16,
          "status_changed_to": null
        },
        "run": {
          "skipped": false,
          "exit_code": 0,
          "signal": null,
          "time": 7.51,
          "status_changed_to": null
        },
        "test": {
          "skipped": false,
          "exit_code": 0,
          "signal": null,
          "time": 0.27,
          "status_changed_to": null
        },
        "post": {
          "skipped": true,
          "exit_code": null,
          "signal": null,
          "time": 0,
          "status_changed_to": null
        }
      },
      "streams": {
        "auxdata": {
          "size": 4200,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.finished/593bf44e-7c0a-4a16-a292-4ab32958e6f1/auxdata"
        },
        "tests_report": {
          "size": 144,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.finished/593bf44e-7c0a-4a16-a292-4ab32958e6f1/tests_report"
        },
        "stage_init_output": null,
        "stage_init_error": null,
        "stage_build_output": {
          "size": 80,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.finished/593bf44e-7c0a-4a16-a292-4ab32958e6f1/stage_build_output"
        },
        "stage_build_error": null,
        "stage_run_output": {
          "size": 1134,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.finished/593bf44e-7c0a-4a16-a292-4ab32958e6f1/stage_run_output"
        },
        "stage_run_error": {
          "size": 567,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.finished/593bf44e-7c0a-4a16-a292-4ab32958e6f1/stage_run_error"
        },
        "stage_test_output": {
          "size": 80,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.finished/593bf44e-7c0a-4a16-a292-4ab32958e6f1/stage_test_output"
        },
        "stage_test_error": null,
        "stage_post_output": null,
        "stage_post_error": null
      }
    }
  }
]
Containers workspace
[
  {
    "origin": "secow",
    "id": "469fcc9d-8686-4100-8b13-480086278226",
    "type": "workspace.scenario.custom",
    "timestamp": 1700570752,
    "payload": {
      "started_at": "2023-11-21 01:33:14 +0000",
      "workspace": {
        "id": "714c7e13fe9c40bd9d47f990317190f1"
      },
      "project": {
        "id": "bb1c27b4aa9e4c7ea74f38c9dd863046",
        "name": "Web React - webhook sample"
      },
      "scenario": "test",
      "stages": {
        "init": {
          "skipped": true,
          "exit_code": null,
          "signal": null,
          "time": 0,
          "status_changed_to": null
        },
        "build": {
          "skipped": false,
          "exit_code": 0,
          "signal": null,
          "time": 4.16,
          "status_changed_to": null
        },
        "run": {
          "skipped": false,
          "exit_code": 0,
          "signal": null,
          "time": 7.51,
          "status_changed_to": null
        },
        "test": null,
        "post": null
      },
      "streams": {
        "auxdata": {
          "size": 4200,
          "uri": "https://containers.sphere-engine.com/api/v1/webhooks/streams/workspace.scenario.custom/557510f4-5b20-4690-86fe-21c29fcc72a7/auxdata"
        }
      }
    }
  }
]
Containers workspace