> ## 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.

# Working with Interactions

> Record non-purchase customer activity through the API, choosing the global or profile-scoped route based on what you know about the customer.

Record a non-purchase event by sending an `action`, a `channel`, and a `signal` to one of the two interaction routes. Which route you use depends on how much you know about the customer at the moment the event happens. For what an interaction is and when one is the right record to create, see [Interactions](/concepts/profiles/interactions.md).

## Choosing a route

There are two ways to create an interaction. Both write the same record; they differ in how the owning profile is determined.

| You have | Use | How the profile is set |
| - | - | - |
| A logged-in session or any context holding the Omneo profile | Profile-scoped `POST /v3/profiles/{profile}/interactions` | Taken from the URL. Any `profile_id` in the body is ignored. |
| Only the Omneo `profile_id`, server-side | Global `POST /v3/interactions` | Sent as `profile_id` in the body. |
| Only an external identity, such as a Shopify customer ID or a loyalty card number | Global `POST /v3/interactions` | Sent as an `identifier`. Omneo resolves it to the profile that holds that identity. |

As a rule, use the profile-scoped route for customer-facing experiences (loyalty apps, member portals, clienteling screens) and the global route for server-side integrations and bulk recording. See [Global vs profile-scoped endpoints](/dev-guides/core-setup/global-vs-profile-routes.md) for the wider pattern.

On the profile-scoped route, creating and editing require the `update-profiles` scope, and browsing and reading require `read-profiles`. The global route uses interaction-specific scopes: `create-interactions` to add, `read-interactions` to browse and read, `update-interactions` to edit, and `delete-interactions` to delete.

## Required fields

Every interaction, on either route, requires five fields.

| Field | Type | Values |
| - | - | - |
| `action` | string | `broadcast`, `disclose`, `feedback`, `product`, `reach`, `refer`, `service`, `visit`, `view` |
| `channel` | string | `app`, `email`, `location`, `push`, `sms`, `social`, `support`, `website` |
| `signal` | integer | `1` positive, `0` neutral, `-1` negative |
| `name` | string | A human-readable label, for example "Viewed product page" |
| `namespace` | string | A handle you define to group related interactions, for example `web-engagement` |

Omneo stores `namespace` in handle format: spaces become hyphens, letters are lowercased, and characters other than letters, digits, `_`, `.` and `-` are removed. Sending `Web Engagement` stores `web-engagement`, so filter and build reactions against the stored form.

## Create an interaction for a known profile

Use the profile-scoped route when you already hold the profile, such as inside a logged-in app session. The profile comes from the URL, so you never send `profile_id`, and an `identifier` in the body is rejected.

```bash theme={null}
curl -X POST https://api.[tenant].getomneo.com/api/v3/profiles/{profileId}/interactions \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "view",
    "channel": "app",
    "signal": 0,
    "name": "Viewed product page",
    "namespace": "web-engagement",
    "product_id": 84217,
    "url": "https://shop.[tenant].com/products/merino-crew"
  }'
```

See [Add Profile Interaction](/api-reference/profile-interaction/add-profile-interaction.md) for the full endpoint reference.

## Create an interaction from a server-side integration

Use the global route when you are recording activity from a backend system. If you hold the Omneo `profile_id`, send it directly.

```bash theme={null}
curl -X POST https://api.[tenant].getomneo.com/api/v3/interactions \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "profile_id": "01HXYZP7Q9N2V8K4M6T1B3C5D7",
    "action": "feedback",
    "channel": "website",
    "signal": -1,
    "name": "Submitted contact form",
    "namespace": "support"
  }'
```

### Identify the customer by an external identity

Often a server-side integration does not hold the Omneo `profile_id`. It knows the customer only by an ID from another system, such as a Shopify customer ID or a loyalty card number. In that case, send an `identifier` instead of `profile_id`. The two are mutually exclusive; send one or the other, not both.

An `identifier` has two parts: a `handle` naming the identity type, and an `id` holding the value. The `handle` must match the handle the [identity](/concepts/profiles/identities.md) is stored under on the profile. Omneo matches against identities only, not against the profile's own email or mobile fields, so an email address identifies a customer here only when your tenant stores email as an identity.

```bash theme={null}
curl -X POST https://api.[tenant].getomneo.com/api/v3/interactions \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "identifier": { "handle": "shopify", "id": "7302145550385" },
    "action": "view",
    "channel": "email",
    "signal": 1,
    "name": "Opened winter campaign email",
    "namespace": "email-engagement"
  }'
```

Omneo looks up the identity by `handle` and value, then attributes the interaction to the profile that identity belongs to. Swap the `handle` for `shopify`, `loyalty-card`, or any identity type your tenant uses.

> [!WARNING]
>
> An `identifier` that matches no existing identity does not return an error. Omneo creates a new identity with that handle and value, linked to no profile, and records the interaction against it with no profile. That interaction does not appear in any profile's interactions and carries no profile into reactions. Make sure the identity exists on the profile before you rely on this route for attribution.

> [!NOTE]
>
> If you frequently need the Omneo `profile_id` for other calls, resolve it once with the identity search endpoint and reuse it. See [Looking up a profile by identity](/dev-guides/profiles/working-with-identities.md#looking-up-a-profile-by-identity).

## Link an interaction to other records

An interaction can connect to other objects, which is what makes it useful for attribution and reporting. Add any of these alongside the required fields.

| Link | Field | Type |
| - | - | - |
| Location | `location_id`, `location_external_id`, or `location_external_code` | integer, string, string |
| Product | `product_id` | integer |
| Product variant | `product_variant_id` | integer |
| Product category | `product_category_id` | integer |
| Staff member | `staff_id` | string (a profile ID) |
| Organisation | `organisation_id` | integer |

A location can be identified by Omneo's `location_id` or by your own `location_external_id` or `location_external_code`, whichever you hold. Omneo tries them in that order and uses the first one that has a value. A location identifier that matches no active location is rejected with a validation error rather than ignored.

To link to an object that does not have a dedicated field, use the polymorphic pair `interacted_type` and `interacted_id`. Set `interacted_type` to the object type and `interacted_id` to its ID. Supported types include `transaction`, `order`, `appointment`, `questionnaire_submission`, `rating`, `reward`, and `benefit`, among others.

```json theme={null}
{
  "action": "feedback",
  "channel": "website",
  "signal": -1,
  "name": "Submitted post-purchase survey",
  "namespace": "support",
  "interacted_type": "questionnaire_submission",
  "interacted_id": 5521
}
```

## Browse and read interactions

Read across all profiles with the global route, or scope to one profile.

```bash theme={null}
# All interactions in the tenant (reporting, integrations)
GET /api/v3/interactions

# Interactions for a single profile (customer-facing)
GET /api/v3/profiles/{profileId}/interactions
```

Both support the standard filtering and pagination described in [Filtering profiles](/dev-guides/profiles/filtering-profiles.md). See [Browse Interactions](/api-reference/interaction/browse-interactions.md) for the global endpoint reference.

## Correct or remove an interaction

Treat interactions as append-only event records: in normal use you create them and move on. The API does expose edit and delete for correcting a mistake or honouring a deletion request, so use them for that, not as part of routine recording.

```bash theme={null}
# Edit (global route requires the update-interactions scope)
PUT /api/v3/interactions/{interactionId}

# Delete (global route requires the delete-interactions scope)
DELETE /api/v3/interactions/{interactionId}
```

Both operations are also available on the profile-scoped route at `/api/v3/profiles/{profileId}/interactions/{interactionId}`.

## Drive incentives from interactions

Each interaction you create fires an `interaction.created` event. That event is available as a [Reaction](/concepts/automation/reactions.md) trigger, so you can act on tracked activity: award points for a product review, issue a benefit on a first app login, or progress an achievement. Filter on fields such as `action`, `channel`, `signal`, or `namespace` to target the exact activity you want to reward.

When the interaction has a profile, the event also carries that profile's name, contact details, statuses and communication preferences, so a reaction can check who the customer is and what they have consented to before it issues anything of value.

## Related

* [Interactions](/concepts/profiles/interactions.md)
* [Identities](/concepts/profiles/identities.md)
* [Working with identities](/dev-guides/profiles/working-with-identities.md)
* [Global vs profile-scoped endpoints](/dev-guides/core-setup/global-vs-profile-routes.md)
* [Interactions API](/api-reference/interaction)
* [Profile Interactions API](/api-reference/profile-interaction)
* [Reactions](/concepts/automation/reactions.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.