> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omneo.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Targets

> Configuring Omneo Targets to send Twig-templated JSON payloads to external endpoints via reactions.

A Target is a configured endpoint that Omneo calls when a reaction fires a `target.send` action. Targets let you push Omneo event data to any service that accepts an HTTP POST, a comms platform, a cloud function, a CRM, or a middleware like Pipedream or Zapier.

## How targets work

1. You create a Target with a URL and a Twig template
2. A reaction fires a `target.send` action referencing the target's handle
3. Omneo renders the template using the event context data
4. Omneo POSTs the rendered JSON to the target URL

## Creating a target

```shell theme={null}
curl -X POST https://api.[tenant].getomneo.com/api/v3/targets \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Profile Update Webhook",
    "handle": "profile-update-target",
    "url": "https://your-endpoint.example.com/omneo",
    "template": "{\"profile\":{\"id\":\"{{ id }}\",\"first_name\":\"{{ first_name }}\",\"last_name\":\"{{ last_name }}\",\"email\":\"{{ email }}\",\"email_promo\":\"{{ attributes.comms.email_promo }}\"}}",
    "description": "Sends profile update events to our comms platform"
  }'
```

## Target templates

Templates are Twig-templated JSON strings. The template is rendered with the event context as its data source.

Unescaped (for readability):

```json theme={null}
{
  "profile": {
    "id": "{{ id }}",
    "first_name": "{{ first_name }}",
    "last_name": "{{ last_name }}",
    "email": "{{ email }}",
    "tier": "{{ tier.handle }}",
    "spend_12m": "{{ aggregations.spend_12m }}",
    "email_promo": "{{ attributes.comms.email_promo }}"
  }
}
```

The variables available in the template depend on the event that fired the reaction. A `profile.updated` trigger provides a profile context; a `transaction.created` trigger provides a transaction context including the linked profile.

See [Event Contexts](/dev-guides/webhooks/event-contexts) for the full context schema per event type.

## Twig operations in templates

Omneo uses the Twig template engine. You can use filters, conditionals, and loops in your template:

```twig theme={null}
{{ first_name | upper }}
{{ aggregations.spend_12m | number_format(2) }}
{% if tier_handle == 'gold' %}VIP{% else %}Standard{% endif %}
```

See the [Twig documentation](https://twig.symfony.com/doc/2.x/templates.html) for the full reference.

## Attaching a target to a reaction

In the reaction's actions array, add a `target.send` action with the target handle:

```json theme={null}
{
  "name": "target.send",
  "sort_order": 2,
  "arguments": [
    {
      "name": "target",
      "value": "profile-update-target",
      "is_dynamic": false
    }
  ]
}
```

## Browsing targets

```shell theme={null}
GET /api/v3/targets
```

## Testing templates with preview

Before attaching a template to a live reaction, use the preview endpoint to render it against a real resource record and see the exact payload Omneo would POST to the target URL.

```shell theme={null}
curl -X POST https://api.[tenant].getomneo.com/api/v3/targets/preview \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "profile",
    "resource_id": "8fc344db-713e-4590-ab26-e82d77ba3313",
    "template": "{\"name\":\"{{ first_name }} {{ last_name }}\",\"tier\":\"{{ tier.handle }}\"}"
  }'
```

Alternatively, pass `target_id` instead of `template` to preview the template already saved on an existing target:

```shell theme={null}
curl -X POST https://api.[tenant].getomneo.com/api/v3/targets/preview \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "resource": "reward",
    "resource_id": "reward-uuid",
    "target_id": 42
  }'
```

Supported values for `resource` are: `profile`, `transaction`, `transaction_item`, `order`, `order_item`, `reward`.

### Success response

```json theme={null}
{
  "data": {
    "result": { "name": "Jane Smith", "tier": "gold" },
    "context": { "id": "8fc344db-...", "first_name": "Jane", ... }
  }
}
```

`result` is the parsed JSON object Omneo would POST to the target. `context` is the full event context used as template variables, so you can see exactly which fields are available.

### Error responses

If the template fails to render or produces invalid JSON, the endpoint returns `422` with an `error` object that identifies where the failure occurred:

```json theme={null}
{
  "error": {
    "stage": "render",
    "message": "Variable 'unknown_field' does not exist.",
    "line": 1
  },
  "rendered_raw": null
}
```

`stage` is either `render` (Twig error) or `json` (the rendered output was not valid JSON). `line` is the template line number for render errors, or `null` for JSON parse errors.

If the resource record cannot be found, the endpoint returns `404`.

The preview endpoint requires the `read-targets` scope.

## Troubleshooting

**No request received at endpoint:**

1. Confirm the reaction is active in CX Manager under Settings → Reactions
2. Check that the reaction fires: add a `target.send` to a known-firing reaction to verify
3. Verify the target URL is correct and accessible
4. Confirm the `target.send` argument references the correct target handle

**Blank or unexpected values in template:**

* Check which object is the root context for the triggering event
* For a `profile.updated` event, `first_name` is at root, use `{{ first_name }}` not `{{ profile.first_name }}`
* When in doubt, POST to a Pipedream or webhook.site endpoint to inspect the raw payload
