> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.etals.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.etals.com/_mcp/server.

# How integrations work

A custom integration with Etals has two directions. Your system pushes product and content data into Etals. Etals produces content (descriptions, meta titles, translations, tags) and pushes it back to your system. Optionally, your system tells Etals when a value needs another pass.

On your side you build one sender and one receiver. Etals configures the rest.

## The round trip

```mermaid
%%{init: {"sequence": {"actorMargin": 150, "messageMargin": 45, "boxMargin": 12, "mirrorActors": false, "wrap": true, "width": 200}}}%%
sequenceDiagram
    participant Y as Your system
    participant E as Etals
    participant R as Your receiver

    Y->>E: POST to your funnel URL
    E-->>Y: 200 accepted
    Note over E: Items are stored, then an automation writes the content
    E->>R: POST the content (up to 100 items)
    R-->>E: 200 OK
    opt A value needs another pass
        R->>E: POST feedback
        E-->>R: 201 Created
        E->>R: POST the new value
    end
```

1. **Your system sends data** to a funnel endpoint, for example every time a product is created or changed in your PIM. See [Data sync via Funnel API](/funnels-api).
2. **Etals stores the items** in a content type, such as **Products**. Fields you did not map are left alone.
3. **Automations start tasks** for the changed items, for example "write a description in Swedish, Norwegian and German when it is missing". A task runs your [pipelines](/pipelines) and [agents](/agents).
4. **Etals sends the results** to your receiver as JSON, when the task finishes (and after approval, if approval is switched on). See [API export](/api-export).
5. **Your system can send feedback** on a value, which creates a task that writes it again. See [API Feedback](/api-feedback).

## What you build

| Part                | What it does                                                                                                                                                                      | Page                                     |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| Sender              | Posts items as JSON to your funnel URL with a Bearer token. Handles `400` per item and retries `5xx`.                                                                             | [Data sync via Funnel API](/funnels-api) |
| Receiver            | An HTTPS endpoint that accepts Etals' `POST`, checks the `Authorization` header, stores each value by identifier, property and localization, and answers `2xx` within 30 seconds. | [API export](/api-export)                |
| Feedback (optional) | Posts reviewer comments with the `value_id` from the export.                                                                                                                      | [API Feedback](/api-feedback)            |

## What Etals configures

| Part                                                         | Who                     | Where                                                                    |
| ------------------------------------------------------------ | ----------------------- | ------------------------------------------------------------------------ |
| Content type and properties, including languages and markets | Etals together with you | [Content types](/content-types), [Properties](/properties)               |
| API token for your sender                                    | You, or Etals for you   | **Settings** > **API Tokens**, see [Authorization](/authorization)       |
| Funnel and field mapping                                     | You, or Etals for you   | **My Apps** > **Funnels**                                                |
| Automations that produce content                             | Etals together with you | Automation builder, with **Publish to your connected platform** selected |
| Custom API export (your receiver URL and secret)             | Etals                   | Configured by your Etals contact                                         |

## Integration checklist

#### Agree on the data

Pick your identifier (for example the SKU `NV-1001`), the fields you send, the properties Etals writes, and the languages and markets. Write down which system owns each field.

#### Get a token

Create a token with **Read**, **Create** and **Delete** from an integration user whose role can manage Funnels and API tokens.

#### Create and map the funnel

Map the identifier, the name and every field you send. Map each language of a translated field to its own localization.

#### Build the sender

Send `Accept: application/json`. Treat `200` as accepted, read item errors from the body, retry only `5xx` and network errors.

#### Build the receiver

Check the shared secret, store values keyed by identifier, property and localization, keep `value_id`, answer `2xx` fast.

#### Send Etals your receiver details

Receiver URL, the secret for the `Authorization` header, an optional staging mirror URL, and the content types to export.

#### Run one product end to end

Send one product, let a task publish, check that your receiver stored the values, then send one feedback request.

## Test it in 5 minutes

This checks the inbound half with nothing but curl. You need a token and a funnel with the **Endpoint URL** `nordvik-products` for your Products content type. Map `sku` to **Identifier** and `name` to **Name**, and leave no other required mappings.

#### Set your variables

```bash
export ETALS_URL="https://{your-workspace}.etals.app"
export ETALS_TOKEN="{api-token}"
```

#### Send one product

```bash
curl -i -X POST "$ETALS_URL/api/v1/funnels/nordvik-products" \
  -H "Authorization: Bearer $ETALS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "sku": "NV-1004", "name": "Midnight Sun Base Layer" }'
```

Expected answer:

```http
HTTP/1.1 200 OK

{"status":"success","message":"Data received successfully."}
```

#### Check what Etals received

Open **My Apps** > **Funnels** > `nordvik-products`. The request is at the top of **Recent Received Requests**. After a few seconds, `NV-1004` appears in the content type.

#### See an error on purpose

Send an item without the identifier:

```bash
curl -i -X POST "$ETALS_URL/api/v1/funnels/nordvik-products" \
  -H "Authorization: Bearer $ETALS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "name": "Tundra 40L Backpack" }'
```

With **Partial Validation** off you get `400` and `errorsWithoutIdentifier` pointing at index `0`.

#### Clean up

```bash
curl -i -X DELETE "$ETALS_URL/api/v1/funnels/nordvik-products" \
  -H "Authorization: Bearer $ETALS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "identifiers": ["NV-1004"] }'
```

To test the outbound half before your real receiver exists, give your Etals contact a temporary request-capture URL as a mirror or main URL, and run a small task on one product.

## Things to know up front

* **Inbound is queued.** A `200` from the funnel means "accepted". The items are stored a few seconds later.
* **Outbound is not retried automatically.** If your receiver is down, the values show as failed in Etals until the export is sent again. On automation tasks, ask your Etals contact to resend. A finished feedback task can be sent again with **Export** > **Integration**. Your receiver must have a public address: Etals doesn't send to private or internal networks. See [Export status and retries](/api-export#export-status-and-retries).
* **Exports are not signed.** Protect your receiver with the shared secret and HTTPS.
* **Duplicates happen.** Make your receiver an upsert keyed on identifier, property and localization.
* **Localizations are explicit.** Every language and market of a property is its own field, in both directions.