> For the complete documentation index, see [llms.txt](https://dev.ubidots.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://dev.ubidots.com/plugins/private-plugins/webhook.md).

# Webhook

## Definition

A private webhook plugin contains user-defined logic that is triggered by an HTTP request to its *HTTPS Endpoint URL*:

<figure><img src="/files/mxWdTkZoj7qxuWwQkveI" alt=""><figcaption></figcaption></figure>

## Required files

As stated before, any private plugin, regardless of its type, and particularly a private webhook plugin, follows the file structure shown below:

```
├── src
│   ├── control     
│   ├── function
│   ├── user_code
│   ├── view.xml
├── LICENSE
├── README.md
├── manifest.toml
```

## control

This is a script written in either Python or NodeJS. Think of it as a setup script, since it runs only once when the plugin is created.

## function

This is a script written in either Python or NodeJS. It contains the plugin's core logic and runs every time an HTTP request is made to the plugin's *HTTPS Endpoint URL*.

## user\_code

This is written either in Python or NodeJS.

If needed, the plugin developer can let users execute custom logic. This script gives users an additional level of customization.

For instance, if a developer creates a webhook plugin to fetch data from an external API, they might want to let users further process or redirect that data without altering the core logic.

The `user_code` script provides that flexibility. It preserves the plugin's encapsulation while offering a dedicated space for user-specific logic.

## Naming convention

You must use the names of all files and directories listed in the "Required files" section, since the plugins engine specifically looks for these files and their extensions.

For instance:

* If your plugin uses Python as its runtime, the script names should be `control.py`, `function.py`, and `user_code.py`
* If your plugin uses NodeJS as its runtime, the script names should be `control.js`, `function.js`, and `user_code.js`

{% hint style="info" %}
The language selected for the `control`, `function`, and `user_code` scripts must match the value of the *`runtime`* key in the `manifest.toml` file.
{% endhint %}

## view\.xml

This file lets the developer build and display a form that users can use to enter the parameters required by the plugin.

The contents of this form are displayed in the plugin creation modal.

For example, if we create a plugin to receive data from an LNS during device uplinks, we would need the user's LNS and Ubidots credentials. A GUI for this plugin could look like this:

<figure><img src="/files/o2FWYRUxhEkEVUD3L04g" alt="" width="563"><figcaption></figcaption></figure>

This can be achieved using text fields in the form as shown below:

```xml
<form name="formName">

    <group name="ttitenantInformation">
        <group name="ttinetworkTenant">
            <label name="tti-tenant-label" help="If you have a TTI Dedicated Cloud license, you can find the Tenant ID as the first portion of your account access URL. [https://www.thethingsindustries.com/docs/getting-started/cloud-hosted/addresses/](Learn more)">TTI Tenant ID</label>
            <input name="tti-tenant" type="text" value="tti"/>
        </group>
    </group>
    
     <group name="group2">
        <group name="ttiapiInformation">
            <label name="tti-api-label" help="A TTS API key with enough permissions to view and list gateways. [https://help.ubidots.com/en/articles/4824641-plugins-monitor-your-tts-lorawan-gateways-with-ubidots](Learn more).">TTI API Key</label>
            <input name="tti-api-key" type="password"/>
        </group>
    </group>

    <group name="ubidotsInformation">
        <group name="fieldToken">
            <label name="labelToken">Ubidots Token</label>
            <token name="token" placeholder="Select Token"/>
        </group>
    </group>

</form>
```

All of these form parameters are accessible to the `function`, `control`, and `user_code` scripts on each execution through the `_parameters` key in the incoming JSON object.

{% hint style="info" %}
For detailed information about the supported elements in the `view.xml` file, refer to its dedicated section in the [Plugins development](https://dev.ubidots.com/plugins/plugins-development/view.xml) page.
{% endhint %}

## LICENSE and README.md files

Refer to the Private Plugins page for more information:

{% content-ref url="/pages/y6JQhF1KBcDzwb9Vtae2" %}
[Private plugins](/plugins/private-plugins.md)
{% endcontent-ref %}

## Manifest.toml

Aside from the manifest components common to all plugin types, the following are specific to webhook plugins:

<table data-full-width="true"><thead><tr><th width="197" align="center">Section</th><th width="210.2" align="center">Key</th><th width="194" align="center">Value</th><th width="205" align="center">Description</th><th align="center">Example</th></tr></thead><tbody><tr><td align="center">[settings]</td><td align="center">runtime</td><td align="center">Any valid Python or NodeJS version.</td><td align="center">Environment in which the plugin will run.</td><td align="center"><code>runtime = "python:3.7"</code></td></tr><tr><td align="center">[settings.webhook]</td><td align="center">default_http_method</td><td align="center">A valid HTTP method.</td><td align="center">Default HTTP method to be used by the plugin.</td><td align="center"><code>default_http_method = "POST"</code></td></tr><tr><td align="center">[settings.webhook]</td><td align="center">allowed_http_methods</td><td align="center">A list of valid HTTP methods.</td><td align="center">HTTP methods allowed by the plugin.</td><td align="center"><code>allowed_http_methods = ["POST"]</code></td></tr></tbody></table>

With that in mind, a typical `manifest.toml` file for a private webhook plugin looks like this:

```
manifest_version = 2.0
 
[settings] 
version = "1.0.56" 
runtime = "python:3.7" 
plugin_type = "webhook" 
license_name = "MIT license" 

[settings.webhook]
default_http_method = "POST"
allowed_http_methods =  ["POST"]
```

{% hint style="info" %}
All of these manifest keys are mandatory.
{% endhint %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://dev.ubidots.com/plugins/private-plugins/webhook.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
