# Webhooks (External)

### Introduction

JourneyApps supports outgoing webhooks that allow remote endpoints to be called when data changes are made.

Webhooks can be configured for a specific model in your Data Model, which will then be triggered when certain conditions are met.

### Configuration

Webhooks are defined in the Data Model of your app, in OXIDE.

To define webhooks to be sent when a specific type of object is created or saved, add a `<webhook/>` element at the end of a `<model/>` definition.

Webhooks can be defined for integrating with internal JourneyApps systems, specifically CloudCode, or with external services.

{% hint style="info" %}
For configuring webhooks with CloudCode, see the [CloudCode -> Webhooks](https://docs.journeyapps.com/reference/cloudcode/triggering-a-cloudcode-task/trigger-cc-via-a-webhook) section.
{% endhint %}

All webhook requests include a signature that can be used to verify the authenticity without needing to configure any shared secrets.

#### Webhooks to External Systems

The configuration options in the `<webhook/>` tag are as follows:

| Configuration Option | Description                                                                                                                                                                                                                                                   |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `type=""`            | The type of webhook, this can be either `ready` or `update`. A `ready` webhook will only be triggered once for a specific object when the conditions are met. An `update` webhook will be triggered each time the object is saved and the conditions are met. |
| `name=""`            | Mandatory name for the webhook.                                                                                                                                                                                                                               |
| `receiver=""`        | Specify "cloudcode" if the webhook should trigger a CloudCode task. See the [CloudCode -> Webhooks](https://docs.journeyapps.com/reference/cloudcode/triggering-a-cloudcode-task/trigger-cc-via-a-webhook) section for further details.                       |
| `action=""`          | The CloudCode task name, if the receiver was specified as "cloudcode".                                                                                                                                                                                        |

Note: Only `type=""` and `name=""` are relevant for webhooks to external systems.

{% hint style="info" %}
Once the webhook has been defined in OXIDE, the endpoint needs to be configured in the Backend. The webhooks will not fire until this has been completed.

This is done through the "Manage Webhooks" link in the user drop-down menu (only available for elevated super-users). All external webhooks will be listed under the "User hooks" section. The "Manage" action for each webhook allows the webhook to be enabled and the endpoint URL to be specified.
{% endhint %}

**Example: External Webhook**

In the example below, we trigger a request to `http://requestb.in/1mwlqhx1` every time that an object of type `resource` is saved.

![](https://2865107717-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F9TCHLR67eLHBOjPvHhud%2Fuploads%2Fgit-blob-d32078aa6cd4176107a250191bcda21e0da5e6e6%2Fexternal-webhook.png?alt=media)

{% code title="schema.xml" %}

```xml
<model name="resource">
    ...
    <webhook type="update" name="external_webhook_name" />
</model>
```

{% endcode %}

The relevant headers for the resulting POST request are as follows:

| Header                                  | Value                                                                                                                                                                                                                                                                                                                                                                                                                             |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `X-Journey-Signature-Rsa-Sha256-Key-Id` | Webhook Verification 1                                                                                                                                                                                                                                                                                                                                                                                                            |
| `X-Journey-Signature-Rsa-Sha256`        | <p>txho18dwBF2BNQpUdh6ji8govTy/kC<br>cE6kBiYQg\ntTE/9uFS2OvRCy8yJa3<br>oT3HtdLMqjb2W7CLVlY\nctdenZnQH<br>tLW7MRtM/KZYNP4h2dwbR/yAbeA\nh<br>XPrWGGizSaSwH+tL6hjNmldvp3jMHi<br>C2E8kK\nvz5z5BkQ0BSII2rLiVO3HX<br>jg4SOlzw/VXMpv8g2\nFtCwaUOA2by<br>kAm/LmPNY/nn2wtLR3rKOhleeA\noh<br>2CEWXM+cx05K01afbFV9oabjgLWXWc<br>TmV\nu/c9ceeUd210SKudpIY3i7lma<br>JWort8w1vXU5SS\ns+wx12KUGMMlDY<br>mCgMWU0cPxP7KoelLaX+\nuUuw7JMg==<br></p> |
| `X-Journey-Signature`                   | b1a6704741054a48363b4e02d89f7d6243b1adf54aa0fa4dd338c5d2949028b4                                                                                                                                                                                                                                                                                                                                                                  |
| `Content-Type`                          | `application/json`                                                                                                                                                                                                                                                                                                                                                                                                                |
| `User-Agent`                            | <p><code>Journey/0.0.1 (Ruby)</code><br></p>                                                                                                                                                                                                                                                                                                                                                                                      |
| (Purely informational)                  |                                                                                                                                                                                                                                                                                                                                                                                                                                   |

The JSON body for the request is as follows:

```json
{
    "account_id": "559d10c922020e45e4000005",
    "app": "my-awesome-webhook-app",
    "event": "external_webhook_name",
    "object": {
        "id": "343dfae00-29a0-11e6-98f3-040173434df01",
        "name": "Sample Resource",
        "photo": {
            "fullscreen": "https://run.journeyapps.com/media/MyImageLFsicCIsImZ1bGxzY3JlZW4iXV0/test-image.png?sha=4756deMYSHA34348d",
            "original": "https:/run.journeyapps.com/media/MyImageLFsicCIsImZ1bGxzY3JlZW4iXV0/test-image.png?sha=4756deMYSHA34348d",
            "state": "uploaded",
            "thumbnail": "https:/run.journeyapps.com/media/MyImageLFsicCIsImZ1bGxzY3JlZW4iXV0/test-image.png?sha=4756deMYSHA34348d"
        },
        "photo_id": "5b534ff-29a0-33fe-11e6-040151508301",
        "type": "resource",
        "updated_at": "2016-06-03T15:32:51Z"
    },
    "operation": "create",
    "sequence": 6291989525132476422,
    "server": "https://run.journeyapps.com"
}
```

{% hint style="warning" %}
The values in `sequence` are large numbers, so make sure that you are using big ints / doubles / similar. Something like [json-bigint](https://www.npmjs.com/package/json-bigint) is required for JavaScript. Take care when testing with services such as requestbin, since they often truncate/round these values.
{% endhint %}

#### Conditions and Embedded Fields

Webhook definitions can optionally contain a number of `field` elements for specifying triggering conditions and embedded attachments or belongs-to objects. The webhook will only trigger once all conditions have been met, regardless of the type of webhook.

The configuration options for the `field` element are as follows:

| Configuration Option | Description                                                                                                                                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name=""`            | The name of the field on which to operate.                                                                                                                                                          |
| `required=""`        | If the field is required or not in order to trigger the webhook (`true` or `false`). Defaults to `true`.                                                                                            |
| `embed=""`           | If the belongs-to related object or attachment should be embedded in the webhook request (`true` or `false`). Defaults to `true`.                                                                   |
| `state=""`           | Set `state` to `uploaded` if the attachment must already have been uploaded. Set `state` to `present` if the attachment need only exist but not necessarily yet be uploaded. Defaults to `present`. |

In the example below, we trigger the event for the `asset_ready` webhook the first time that the `asset_photo` attachment field is set and uploaded and the `user` (`belongs-to` relationship) is set. The `asset_photo` attachment field is embedded in the webhook request.

{% code title="schema.xml" %}

```xml
<model name="asset" label="Asset">
    <field name="name" label="Name" type="text:name"/>
    <field name="asset_photo" label="Asset Photo" type="photo" />

    <belongs-to model="user" />

    <display>{name}</display>

    <webhook type="ready" name="asset_ready">
        <field name="asset_photo" required="true" embed="true" state="uploaded" />
        <field name="user" required="true" embed="false" />
    </webhook>
</model>
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.journeyapps.com/reference/app-features/webhooks-external.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
