# Private plugins

{% hint style="info" %}
This feature requires an Enterprise license. Please contact <sales@ubidots.com> to enable the *developer console* on your account.
{% endhint %}

Private plugins, unlike their public counterparts, are developed, maintained, and deployed by Ubidots **users** to meet requirements that the platform does not address natively.

A private plugin is structured around a specific set of files. These files not only determine the plugin type but also define its logic and overall functionality. The typical file structure for a plugin, regardless of its type, is outlined below:

```
├── src
│   ├── some_files_or_folders    
├── LICENSE
├── README.md
├── manifest.toml 
```

{% hint style="warning" %}
Following this file structure and including all the listed files is required for the plugin to deploy and work correctly.
{% endhint %}

## src directory

The `src` directory holds the primary components of the plugin. This is where the core logic, main functionality, and some configuration files are defined.

For more details about the contents of this directory, refer to the dedicated section for each plugin type:

{% content-ref url="/pages/7MziWvY1O31Eqt6xd5nm" %}
[Cron](/plugins/private-plugins/cron.md)
{% endcontent-ref %}

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

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

{% content-ref url="/pages/2ba8br8YpAqOor51WY1E" %}
[Device](/plugins/private-plugins/device.md)
{% endcontent-ref %}

## manifest.toml

In broad terms, the manifest file defines the plugin's identity and behavior. It outlines:

* The plugin type
* The current plugin version
* The plugin price
* Environment variables

This file contains both shared components that apply to all plugin types and unique components that are specific to each plugin type.

The typical manifest file common to all plugins is composed of:

<table data-full-width="true"><thead><tr><th width="168.2" align="center">Section</th><th width="178" align="center">Key</th><th width="202" align="center">Value</th><th width="199" align="center">Description</th><th align="center">Example</th></tr></thead><tbody><tr><td align="center">[-]</td><td align="center">manifest_version</td><td align="center">A valid manifest version. Currently 2.0 is the only one supported.</td><td align="center">Manifest version.</td><td align="center"><pre><code>manifest_version = 2.0
</code></pre></td></tr><tr><td align="center">[settings]</td><td align="center">version</td><td align="center">Any number, according to your versioning system.</td><td align="center">Plugin's current version.</td><td align="center"><pre><code>version = "1.1.1"
</code></pre></td></tr><tr><td align="center">[settings]</td><td align="center">plugin_type</td><td align="center">cron, webhook, device, widget.</td><td align="center">Type of plugin</td><td align="center"><pre><code>plugin_type = "widget"
</code></pre></td></tr><tr><td align="center">[settings]</td><td align="center">license_name</td><td align="center">A valid license name.</td><td align="center">The name for your plugin's license.</td><td align="center"><pre><code>license_name = "MIT license"
</code></pre></td></tr><tr><td align="center">[pricing]</td><td align="center">price*</td><td align="center">A float number.</td><td align="center">This is the price that the developer wants to set for the plugin.</td><td align="center"><pre><code>price = 10
</code></pre></td></tr><tr><td align="center">[environment]</td><td align="center">Any variable name*</td><td align="center">Any value for the variable.</td><td align="center">Allows to set environment variables within the plugin.</td><td align="center"><code>UBIDOTS_URL = "https://industrial.api.ubidots.com"</code></td></tr></tbody></table>

With that in mind, a manifest file that is common to all plugins, regardless of their type, looks like this:

```
manifest_version = 2.0

[settings]
version = "1.1.1"
plugin_type = "cron" | "webhook" | "device" | "widget"
license_name = "MIT license"

[pricing]
price = 10

[environment]
UBIDOTS_URL = "https://industrial.api.ubidots.com"
```

For detailed information about the specific manifest file components particular to each plugin type, refer to their dedicated pages.

{% hint style="info" %}
Manifest file keys marked with a \* are optional.
{% endhint %}

## Runtimes

### Python

The plugin's Python runtime is based on Python 3.11. Use `python3.11` in the `manifest.toml` file. It includes the following libraries:

<table><thead><tr><th width="432" align="center">Library</th><th align="center">Version</th></tr></thead><tbody><tr><td align="center">requests</td><td align="center">2.32.3</td></tr><tr><td align="center">pytz</td><td align="center">2024.1</td></tr><tr><td align="center">msgpack</td><td align="center">1.0.8</td></tr><tr><td align="center">httpx</td><td align="center">0.27.0</td></tr><tr><td align="center">aiohttp</td><td align="center">3.9.5</td></tr><tr><td align="center">lxml</td><td align="center">5.2.2</td></tr><tr><td align="center">numpy</td><td align="center">2.0.0</td></tr><tr><td align="center">pandas</td><td align="center">2.2.2</td></tr><tr><td align="center">python-aqi</td><td align="center">0.6.1</td></tr></tbody></table>

### NodeJS <a href="#h_a6f43dab0f" id="h_a6f43dab0f"></a>

The plugin's NodeJS runtime is based on NodeJS 20. Use `nodejs:20` in the `manifest.toml` file. It includes the following libraries:

<table><thead><tr><th width="176" align="center">Library</th><th align="center">Version</th></tr></thead><tbody><tr><td align="center">axios</td><td align="center">1.5.1</td></tr></tbody></table>

## License

The `LICENSE` file provides information about the licensing terms under which the plugin is distributed.

Typically, a license file looks like this:

```

Copyright (c) 2021 Ubidots

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
```

{% hint style="warning" %}
This file can't be empty.
{% endhint %}

## README

This file is as important as the `src` directory because it guides plugin users. This file must be written in Markdown.

{% hint style="warning" %}
This file can't be empty.
{% endhint %}


---

# 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://dev.ubidots.com/plugins/private-plugins.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.
