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

# Workflows — intégrations & interpolation

> Les actions webhook et e-mail, identifiants sécurisés, décalages de date et la syntaxe du modèle d'interpolation.

Au-delà des actions de plan, les workflows peuvent appeler des systèmes externes et envoyer des e-mails — et n'importe quel champ
peut référencer des valeurs antérieures via l'interpolation.

## CALL\_WEBHOOK

```json theme={null}
{
  "actionType": "CALL_WEBHOOK",
  "url": "https://example.com/hook",
  "method": "POST",
  "headers": [ { "key": "X-Source", "value": "solya" } ],
  "queryParams": [ { "key": "ref", "value": "{{workflow.id}}" } ],
  "bodyType": "json",
  "bodyTemplate": "{ \"plan\": \"{{steps.create.output.planId}}\" }",
  "auth": { "type": "bearer", "credentialId": "<uuid>" },
  "timeoutMs": 10000,
  "retries": { "count": 2, "backoffMs": 1000 },
  "successStatusCodes": [200, 201, [200, 299]],
  "saveResponseAs": "hookResult"
}
```

| Champ                                           | Signification                                                                                                              |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `method`                                        | `GET` · `POST` · `PUT` · `PATCH` · `DELETE`.                                                                               |
| `url`, `headers`, `queryParams`, `bodyTemplate` | Tous supportent [l'interpolation](#interpolation).                                                                         |
| `bodyType`                                      | `none` · `json` · `form` · `raw` (`bodyContentType` pour `raw`).                                                           |
| `auth`                                          | `{ type: "none" }`, ou `bearer` / `basic` / `apiKey` référençant un `credentialId` (`apiKey` prend aussi un `headerName`). |
| `timeoutMs` / `retries`                         | Politique d'exécution (`retries`: `{ count, backoffMs }`).                                                                 |
| `successStatusCodes`                            | Codes (ou plages `[from, to]`) traités comme succès.                                                                       |
| `saveResponseAs`                                | Nomme la sortie de réponse pour qu'elle soit accessible en aval.                                                           |

## SEND\_EMAIL

```json theme={null}
{
  "actionType": "SEND_EMAIL",
  "to": ["buyer@example.com"],
  "cc": [], "bcc": [], "replyTo": "ops@solya.app",
  "fromAddress": "no-reply@solya.app",
  "fromName": "Solya",
  "subject": "Restock plan {{steps.create.output.planName}} ready",
  "bodyFormat": "markdown",
  "bodyTemplate": "Added **{{steps.add.output.addedCount}}** items.",
  "tags": ["restock"],
  "trackOpens": true,
  "trackClicks": false
}
```

Envoyé via Mailgun à partir d'un domaine expéditeur vérifié. `bodyFormat` est `text`, `html`, ou
`markdown`. **Sortie :** `messageId`.

## Identifiants

Les secrets webhook ne vivent jamais dans la définition de flux — ils sont stockés séparément et
référencés par `credentialId`.

* Types : `BEARER_TOKEN`, `BASIC_AUTH`, `API_KEY`.
* Stockés **chiffrés au repos** (AES-256-GCM) ; le flux ne tient que l'id de l'identifiant.
* L'app expose une **vue sécurisée** (id, name, type — jamais le secret) ; le secret est
  résolu côté serveur uniquement quand la plateforme données exécute l'appel.

## Décalages de date

Les dates du plan (`deadline`, `startDate`, `endDate`) utilisent un `DateOffset` :

| Genre          | Format                                                              | Signification                  |
| -------------- | ------------------------------------------------------------------- | ------------------------------ |
| `absolute`     | `{ "kind": "absolute", "iso": "2026-09-01T00:00:00Z" }`             | Une date-heure ISO fixe.       |
| `relative`     | `{ "kind": "relative", "offsetDays": 30 }`                          | N jours à partir de `{{now}}`. |
| `interpolated` | `{ "kind": "interpolated", "template": "{{steps.x.output.date}}" }` | Résolu à partir d'un modèle.   |

## Interpolation

N'importe quel champ interpolé utilise `{{ … }}` avec la notation par points. La résolution se fait à l'exécution sur
la plateforme données (le générateur offre l'autocomplétion).

**Variables statiques**

| Variable                                          | Valeur                                                   |
| ------------------------------------------------- | -------------------------------------------------------- |
| `{{trigger.entityType}}` / `{{trigger.entityId}}` | Le type d'entité déclencheur / premier id correspondant. |
| `{{org.id}}` / `{{org.name}}`                     | L'organisation.                                          |
| `{{workflow.id}}` / `{{workflow.name}}`           | Le workflow.                                             |
| `{{now}}`                                         | Horodatage ISO au démarrage de l'exécution.              |

**Sorties d'étape** — `{{steps.<nodeId>.output.<field>}}`, par ex. :

* create-plan: `planId`, `planType`, `planName`, `isNew`
* add-items: `addedCount`, `skippedCount`
* webhook: votre champ `saveResponseAs`
* email: `messageId`

<Note>
  Les noms de sortie s'alignent avec les enregistrements d'étape — voir
  [Exécutions & exemples](/fr/developers/workflows/runs-and-examples).
</Note>
