Close
    logoCloudomation Docs

    Webhooks

    With webhooks you can create REST endpoints which create Cloudomation executions when called.

    Use Cases

    Use webhooks to

    • start Cloudomation executions from third party systems
    • receive notifications from third party systems
    • receive callbacks from asynchrounous processes running in third party systems
    • create custom status HTML pages which display information gathered from Cloudomation
    • expose information or functionality to consumers which do not have a Cloudomation user

    Concept

    As long as an enabled webhook exists in Cloudomation the REST endpoint is available to receive calls.

    webhooksInternetInternetWebhookWebhookInternet->WebhookExecutionExecutionWebhook->ExecutionIntranetIntranetIntranet->Webhook

    HTTP method

    The endpoint accepts the HTTP methods GET, DELETE, HEAD, POST, PUT, and PATCH. The method which was used is passed to the execution. If the HTTP method allows for a body payload and a body payload was provided, it is also passed to the execution.

    A HTTP GET request should only be used to retrieve a resource, while a HTTP POST request should be used to create a resource. Calling a Cloudomation webhook creates an execution. Thus the recommended way to call a webhook is by using a POST request. For compatibility reasons Cloudomation also allows calling webhooks using a GET request.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger".

    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    # the execution will receive in the input_value:
    # {"method": "GET"}
    curl -X PUT https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    # the execution will receive in the input_value:
    # {"method": "PUT"}
    curl -X DELETE https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    # the execution will receive in the input_value:
    # {"method": "DELETE"}

    Path

    Each webhook creates a base URL where it can be called. All calls below that base URL are also accepted. The path which was used is also passed to the execution.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger".

    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    # the execution will receive in the input_value:
    # {"path": None}
    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call/
    # the execution will receive in the input_value:
    # {"path": ""}
    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call/some/path
    # the execution will receive in the input_value:
    # {"path": "some/path"}

    Headers

    All HTTP headers which are sent from the client are passed to the execution.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger".

    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call -H "my-header: value"
    # the execution will receive in the input_value:
    # {"headers": {"my-header": "value"}}
    Curl also sets other headers which are passed to the execution. For brevity they were omitted from the example above.

    Query parameters

    All query parameters which are used are passed to the execution.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger".

    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    # the execution will receive in the input_value:
    # {"query": {}}
    curl https://jollyroger.cloudomation.com/api/latest/webhook/captain/call?mode=search&q=foo
    # the execution will receive in the input_value:
    # {"query": {"mode": "search", "q": "foo"}}

    Configuration

    Please see the table below for the different webhook fields and their meanings.

    FieldDescription
    FlowThe flow which is started when the webhook is called
    EnabledIf unset, the HTTP endpoint is not available
    Is productiveIf set, the executions are started in productive mode. See Development and Productive Mode.
    Require login token cookieIf set, the client has to provide a valid Cloudomation login token for the call to succeed. See Authentication. The execution will additionaly receive auth in the input_value containing information about the Cloudomation user.
    KeyAn API key. If set, the client has to provide the API key for the call to succeed. The API key can be specified as a query parameter or as a key in a JSON payload.
    URLA preview of the base URL of the webhook (Readonly)
    When a new webhook is created, a random API key will be generated for you.

    Public webhooks

    A webhook can be considered public when it requires neither a login token nor an API key. For cloud workspaces, a public webhook can be called by anybody on the internet. For on-premise installations, public webhooks can be called by anybody who has network access to your Cloudomation workspace.

    Be considerate and careful when exposing a public webhook. Always validate untrusted user input!

    Private webhooks

    A webhook can be considered private when it requires a login token and/or an API key.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger" which requires a login token.

    # call without a token
    $ curl -i https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 401 Unauthorized
    ...
    "401 Unauthorized"
    # call with a token
    $ curl -i -H "x-cloudomation-token: ey..." https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 200 OK
    Example

    Consider a webhook named "captain" in the workspace "jollyroger" which requires an API key.

    # call without API key
    $ curl -i https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 401 Unauthorized
    # call with API key in the headers
    $ curl -i -H "Authorization: Bearer my-secret-key" https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 200 OK
    # call with API key in query parameter
    $ curl -i https://jollyroger.cloudomation.com/api/latest/webhook/captain/call\?key=my-secret-key
    HTTP/1.1 200 OK
    # when using a method which allows for a body payload
    # the API key can also be specified in the JSON body
    $ curl -i -H "Content-Type: application/json" -d '{"key": "my-secret-key"}' -X POST https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 200 OK
    The value of the API key will not be passed to the execution.
    If the API key is specified in multiple places, they will be applied in the order: body payload -> query parameter -> authentication header

    Synchronous and asynchronous webhooks

    Per default webhooks are called synchronously. The HTTP call will block until the execution reaches the ENDED_SUCCESS status. In synchronous mode the output_value of the execution will be returned to the client in the response payload as JSON.

    It is possible to call a webhook asynchronously by adding async to the query parameters. In asynchronous mode the HTTP response code will be 201 (Created) and the ID of the created execution will be returned in the response body.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger".

    # synchronous mode, the output_value is returned as JSON
    $ curl -i https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    ...
    {"output": "value", "returned": "here"}
    # asynchronous mode, the execution ID is returned as plaintext
    $ curl -i https://jollyroger.cloudomation.com/api/latest/webhook/captain/call\?async
    HTTP/1.1 201 Created
    Content-Type: text/plain; charset=utf-8
    ...
    aeae71f4-b062-4655-a333-d4d58014cf64
    Do not use synchronous webhooks for long-running executions. In most cases a HTTP timeout will interrupt your query. The execution will continue running though.

    Error handling

    When the execution does not end with ENDED_SUCCESS Cloudomation will return the HTTP status 500 (Internal Server Error). The status and the status message of the execution will be returned in the response body.

    Example

    Consider a webhook named "captain" in the workspace "jollyroger".

    $ curl -i https://jollyroger.cloudomation.com/api/latest/webhook/captain/call
    HTTP/1.1 500 Internal Server Error
    Content-Type: text/plain; charset=utf-8
    ...
    ENDED_ERROR: status-message which was set by the execution

    Custom responses

    You can return custom responses from webhooks. There are three helper methods available:

    Example

    Use of a custom response to perform a redirect

    The helper webhook_response allows for customization of status, headers, and body:

    import flow_api
    def handler(system: flow_api.System, this: flow_api.Execution):
    return this.webhook_response(
    status=302, # the HTTP status code to return
    headers={ # Additional HTTP headers to return
    'Location': 'https://cloudomation.com',
    },
    body='response-body', # The body payload to return
    )

    The helper webhook_html_response accepts a HTML string and will set the status to HTTP 200 and content-type to text/html:

    Example

    Use of a custom HTML response

    import random
    import flow_api
    def handler(system: flow_api.System, this: flow_api.Execution):
    return this.webhook_html_response(
    body=(
    f'''
    <h1>Welcome to my homepage</h1>
    <p>Rolling the dice: {random.randint(1,6)}</p>
    <a href="call">roll again</a>
    '''
    ),
    )

    The helper webhook_json_response accepts any object which can be JSON serialized and will set the status to HTTP 200 and content-type to application/json:

    Example

    Use of a custom JSON response

    import flow_api
    def handler(system: flow_api.System, this: flow_api.Execution):
    return this.webhook_json_response(
    body={
    "some": [
    "nested",
    "object",
    ],
    },
    )

    CRUD Example

    The following is a simple flow script which implements a REST API for a food store. It shows how to read the path of the endpoint and return a custom body and HTTP status.

    import json
    import flow_api
    def handler(system: flow_api.System, this: flow_api.Execution):
    input = this.get('input_value')
    storage_setting = system.setting("food store")
    try:
    storage_setting.get("value")
    except flow_api.exceptions.ResourceNotFoundError:
    storage_setting.save(
    value=[
    {
    "name": "apple",
    "price": 1,
    },
    {
    "name": "banana",
    "price": 2,
    },
    ]
    )
    storage_setting.acquire()
    storage = storage_setting.get("value")
    status = None
    body = None
    if input['method'] == 'GET':
    if not input['path']:
    status = 200
    body = storage
    else:
    for item in storage:
    if item["name"] == input["path"]:
    status = 200
    body = item
    break
    elif input["method"] == 'POST':
    item = {
    "name": input["json"]["name"],
    "price": input["json"]["price"],
    }
    storage.append([item])
    storage_setting.save(value=storage)
    body = item
    status = 201
    elif input["method"] == 'DELETE':
    storage = [x for x in storage if x["name"] != input["path"]]
    storage_setting.save(value=storage)
    body = ""
    status = 200
    elif input["method"] == 'PATCH':
    for item in storage:
    if item["name"] == input["path"]:
    item["name"] = input["json"].get("name", item["name"])
    item["price"] = input["json"].get("price", item["price"])
    storage_setting.save(value=storage)
    body = item
    status = 200
    break
    return this.webhook_response(
    status=status,
    body=json.dumps(body),
    )
    Example

    List all items in the food store

    curl -X GET https://jollyroger.cloudomation.com/api/latest/webhook/food/call
    [{"name": "banana", "price": 2}, {"name": "apple", "price": 1}]
    Example

    Get the food with name "apple"

    curl -X GET https://jollyroger.cloudomation.com/api/latest/webhook/food/call/apple
    {"name": "apple", "price": 1}
    Example

    Delete a food item.

    curl -X DELETE https://jollyroger.cloudomation.com/api/latest/webhook/food/call/apple
    Example

    Create a new food item

    curl -X POST https://jollyroger.cloudomation.com/api/latest/webhook/food/call -d '{"name": "apple", "price": 2}' -H 'Content-Type: application/json'
    {"name": "apple", "price": 2}
    Example

    Update an existing item

    curl -X PATCH https://jollyroger.cloudomation.com/api/latest/webhook/food/call/apple -d '{"price": 1}' -H 'Content-Type: application/json'
    {"name": "apple", "price": 1}

    ToDo App Example

    A small ToDo web application implemented using a Cloudomation webhook can be found in the flow script library:

    https://github.com/starflows/library/blob/develop/todo.py

    Knowledge Base — Previous
    Vault Integration
    Next — Knowledge Base
    Workspace Configuration