> For the complete documentation index, see [llms.txt](https://docs.mediarithmics.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.mediarithmics.io/setup-and-monitor/extend-the-platform/build-a-custom-feed-plugin.md).

# Build a custom feed plugin

Build an audience segment external feed to push segments to a partner the platform does not connect to.

## Your goal

Push audience segments to a system no existing connector covers, by writing and deploying an audience segment external feed plugin.

## Expected outcome

A `LIVE` plugin version your users can attach to a segment, sending data to your partner reliably and within their rate limits.

## Before you start

* Read [Plugin architecture](/setup-and-monitor/extend-the-platform/plugin-architecture.md). The plugin, version, worker, instance, and property model is what the rest of this page assumes.
* Confirm no existing connector fits - check the `Connectors` section first.
* Decide **how the partner wants the data**: unit updates, batches, files, or a pixel shown in the browser.

## The two shapes of a feed

| Shape                  | What it does                                                           |
| ---------------------- | ---------------------------------------------------------------------- |
| **Server-side stream** | Your plugin receives user segment updates and calls the partner's API. |
| **Pixel**              | A pixel is shown to users in the segment, in the browser.              |

A feed can also write files instead of calling an API, through the **file delivery service** - see [File destination](/setup-and-monitor/collect-and-manage-your-data/export-your-data/file-destination.md). If it does, set the **Use file delivery** parameter on the version; it is optional and defaults to `false`.

## Create and deploy

The plugin type is `AUDIENCE_SEGMENT_EXTERNAL_FEED` for a server-side feed, or `AUDIENCE_SEGMENT_TAG_FEED` for a pixel feed.

{% stepper %}
{% step %}

### Create the plugin

In the Computing Console, click **New Plugin** and configure:

| Parameter        | What to set                                                                                                                                                                                                    |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Plugin type**  | One of `ACTIVITY_ANALYZER`, `ATTRIBUTION_PROCESSOR`, `AUDIENCE_SEGMENT_EXTERNAL_FEED`, `AUDIENCE_SEGMENT_TAG_FEED`, `COMPUTED_FIELD_FUNCTION`, `DISPLAY_AD_RENDERER`, `ML_FUNCTION`, `SCENARIO_CUSTOM_ACTION`. |
| **Organisation** | Defines availability. `1` or `100` makes the plugin accessible to **all** organisations; any other value restricts it to that organisation and its sub-organisations.                                          |
| **Group ID**     | Categorises plugins, typically by customer and type: `com.mycustomer.plugintype` for a customer-specific plugin, `com.mediarithmics.plugintype` for a shared one.                                              |
| **Artifact ID**  | A unique identifier for your plugin. **Must not be the same as the group ID.**                                                                                                                                 |

Or by API:

```
POST https://api.mediarithmics.com/v1/plugins
```

```json
{
  "plugin_type": "AUDIENCE_SEGMENT_EXTERNAL_FEED",
  "organisation_id": "1234",
  "group_id": "com.company.audience.externalfeed",
  "artifact_id": "partner-connector"
}
```

{% endstep %}

{% step %}

### Create a version

| Parameter             | What to set                                                               |
| --------------------- | ------------------------------------------------------------------------- |
| **Version**           | `1.0.0`, `1.2.0`, or `1.2.0-rcl` - three digits with an optional suffix.  |
| **Engine type**       | The system where the plugin is executed.                                  |
| **Plugin properties** | The context sent to your plugin. `provider` and `name` are **mandatory**. |

```
POST https://api.mediarithmics.com/v1/plugins/:plugin_id/versions
```

The body carries `version_id`, `plugin_properties`, optionally `maintainerId`, and optionally `file_delivery_activated` - `false` by default.

The version starts as `DRAFT`: editable, and not available to customers.

{% hint style="info" %}
When defining the properties your code needs, you can reuse properties from your test files - but **remove any default values** before finalising the configuration.
{% endhint %}
{% endstep %}

{% step %}

### Add configuration files

A configuration file stores credentials, connection parameters, or technical settings for a specific customer, organisation, or datamart - API keys, authentication tokens, endpoint URLs. It keeps configuration adaptable without modifying the plugin code.

In the interface, they are under **Technical Configuration** on the plugin version: **Add a Technical Configuration**, give it a name, and define the content in **JSON**.

By API:

```
PUT https://api.mediarithmics.com/v1/plugins/:plugin_id/versions/:version_id/configuration_file/technical_name=:technical_name
```

{% hint style="danger" %}
Configuration files hold credentials. Keep them in the platform, not in your repository, and not in a ticket.
{% endhint %}
{% endstep %}

{% step %}

### Declare external services

If your code calls external APIs - a CRM, a partner API, a recommendation engine - **you must whitelist them**.

```
POST https://api.mediarithmics.com/v1/plugins/:pluginId/versions/:versionId/external_services
```

The response includes an `enabled` field, and it may be `false`.

{% hint style="warning" %}
mediarithmics needs to enable each host the first time it is added as an external service. **Contact your account manager with the ID of the external service** you want enabled - until then your calls will not go through.
{% endhint %}
{% endstep %}

{% step %}

### Deploy the build

In the interface, open the **Overview** tab of your version and click **Deploy the version**. For an engine type of `HOSTED_CONTAINERS`, enter your **build tag**; the status becomes `DEPLOYING` while containers are created, then `TESTING`.

By API:

```
POST https://api.mediarithmics.com/v1/plugins/:pluginId/versions/:versionId/containers/action
```

{% hint style="info" %}
Deployment can take **5 to 10 minutes**.
{% endhint %}
{% endstep %}

{% step %}

### Check the deployment

For `HOSTED_CONTAINERS` plugins, verify that the version is deployed in **running containers** - **if no containers are running, the version is not usable**.

In the Computing Console, select your plugin and version, and open the **Deployment** tab to see the name and number of running containers.
{% endstep %}

{% step %}

### Move it to LIVE

`TESTING` is visible to organisation administrators only, and users cannot create instances from it. Once validated, set the version to `LIVE`. See [the version lifecycle](/setup-and-monitor/extend-the-platform/plugin-architecture.md#versions).
{% endstep %}
{% endstepper %}

## Write the plugin so it survives a second instance

The same version is attached by your users to several segments, each creating an [instance](/setup-and-monitor/extend-the-platform/plugin-architecture.md#instances). Your code must read its instance rather than assume one configuration:

1. Find the instance ID in the request body.
2. Fetch - and cache - the properties of that instance.
3. Process according to that configuration.

The Plugin SDK does this for you. See [Plugin architecture](/setup-and-monitor/extend-the-platform/plugin-architecture.md#properties) for the property model.

## Respect the partner's limits

Partner APIs have their own rate limits, and a plugin that does not handle the resulting errors well will fail in production. Configure a **throttling** on the plugin version - calls per second, concurrency, and timeout - rather than relying on the partner to be forgiving. See [Plugin architecture](/setup-and-monitor/extend-the-platform/plugin-architecture.md#controlling-how-hard-a-plugin-is-called).

If the partner needs **batched** input rather than one user at a time, see [Batching for feeds](/setup-and-monitor/extend-the-platform/build-a-custom-feed-plugin/batching-for-feeds.md).

## Verify

* The version reaches `LIVE`, with running containers.
* Every external host your code calls is declared **and enabled**.
* Two instances of the same version, configured differently, behave differently.
* A test segment reaches the partner with the expected payload.
* Throttling keeps you inside the partner's limits under load.

## Related pages

<table data-view="cards" data-search="false"><thead><tr><th></th><th></th><th data-hidden data-card-target data-type="content-ref"></th></tr></thead><tbody><tr><td><strong>Batching for feeds</strong></td><td>Sending batches instead of unit updates.</td><td><a href="/setup-and-monitor/extend-the-platform/build-a-custom-feed-plugin/batching-for-feeds.md">Batching for feeds</a></td></tr><tr><td><strong>Plugin architecture</strong></td><td>Versions, instances, properties, throttlings.</td><td><a href="/setup-and-monitor/extend-the-platform/plugin-architecture.md">Plugin architecture</a></td></tr><tr><td><strong>File destination</strong></td><td>File-based delivery, and the grouping key.</td><td><a href="/setup-and-monitor/collect-and-manage-your-data/export-your-data/file-destination.md">File destination</a></td></tr></tbody></table>


---

# 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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.mediarithmics.io/setup-and-monitor/extend-the-platform/build-a-custom-feed-plugin.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
