---
title: Flussi operativi
description: Tre flussi end-to-end con l'API REST partner — apertura opportunità, invio preventivo e tracking della firma di un contratto.
---

Questa pagina mette in fila le risorse delle guide precedenti in tre **flussi
end-to-end**, così come li affronterebbe un'integrazione server-to-server: dalla
nascita di un'opportunità all'invio di un preventivo, fino al tracking della
firma di un contratto.

Tutti gli esempi usano l'host `https://api.audin.ai` e l'header `X-API-Key`.
Per i campi completi di ogni risorsa fai riferimento alle guide per gruppo e
allo [Swagger](https://api.audin.ai/docs/partners).

## Flusso 1 — Apertura di un'opportunità

Obiettivo: creare un'**azienda**, un **lead** di contatto e aprire una **deal**
nella pipeline di vendita.

<Steps>
<Step>
Crea l'azienda con `POST /companies` e conserva l'`id` ritornato.
</Step>
<Step>
Crea il lead con `POST /leads`, associandolo all'azienda via `companyId`.
</Step>
<Step>
Recupera la pipeline di tipo `DEAL` (`GET /pipelines?type=DEAL`) e il suo primo
stage.
</Step>
<Step>
Crea la deal con `POST /deals`, indicando `pipelineId`, `stageId` e — per
collegare i protagonisti — `primaryContactId`, `companyIds` e `contactIds`.
</Step>
</Steps>

<Tabs items={["curl", "JavaScript"]}>
<Tab value="curl">

```bash
BASE="https://api.audin.ai"

# 1. Crea l'azienda
COMPANY_ID=$(curl -sX POST $BASE/companies \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Acme Srl","domain":"acme.example.com"}' \
  | jq -r '.id')

# 2. Crea il lead associato
LEAD_ID=$(curl -sX POST $BASE/leads \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"fullName\": \"Mario Rossi\",
    \"email\": \"mario@acme.example.com\",
    \"phoneNumber\": \"+393331234567\",
    \"companyId\": \"$COMPANY_ID\"
  }" | jq -r '.id')

# 3. Recupera pipeline DEAL e primo stage
PIPELINES=$(curl -s "$BASE/pipelines?type=DEAL" \
  -H "X-API-Key: $API_KEY")
PIPELINE_ID=$(echo "$PIPELINES" | jq -r '.[0].id')
STAGE_ID=$(echo "$PIPELINES" | jq -r '.[0].stages[0].id')

# 4. Crea la deal collegata a lead e azienda
curl -X POST $BASE/deals \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"title\": \"Opportunità Acme\",
    \"pipelineId\": \"$PIPELINE_ID\",
    \"stageId\": \"$STAGE_ID\",
    \"amount\": 5000,
    \"currency\": \"EUR\",
    \"primaryContactId\": \"$LEAD_ID\",
    \"companyIds\": [\"$COMPANY_ID\"],
    \"contactIds\": [\"$LEAD_ID\"]
  }"
```

</Tab>
<Tab value="JavaScript">

```js
const BASE = "https://api.audin.ai";
const headers = {
  "X-API-Key": process.env.AUDIN_API_KEY,
  "Content-Type": "application/json",
};

// 1. Crea l'azienda
const company = await (
  await fetch(`${BASE}/companies`, {
    method: "POST",
    headers,
    body: JSON.stringify({ name: "Acme Srl", domain: "acme.example.com" }),
  })
).json();

// 2. Crea il lead associato
const lead = await (
  await fetch(`${BASE}/leads`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      fullName: "Mario Rossi",
      email: "mario@acme.example.com",
      phoneNumber: "+393331234567",
      companyId: company.id,
    }),
  })
).json();

// 3. Recupera pipeline DEAL e primo stage
const pipelines = await (
  await fetch(`${BASE}/pipelines?type=DEAL`, { headers })
).json();
const { id: pipelineId, stages } = pipelines[0];

// 4. Crea la deal collegata a lead e azienda
const deal = await (
  await fetch(`${BASE}/deals`, {
    method: "POST",
    headers,
    body: JSON.stringify({
      title: "Opportunità Acme",
      pipelineId,
      stageId: stages[0].id,
      amount: 5000,
      currency: "EUR",
      primaryContactId: lead.id,
      companyIds: [company.id],
      contactIds: [lead.id],
    }),
  })
).json();
```

</Tab>
</Tabs>

<Callout type="info">
  Vedi [CRM anagrafiche](/docs/api-rest/crm) per i campi di lead e aziende e
  [Pipeline & deal](/docs/api-rest/pipeline-e-deal) per quelli della deal.
</Callout>

## Flusso 2 — Invio di un preventivo

Obiettivo: generare un **preventivo** da un template e recapitarlo al contatto
della deal. Il preventivo eredita le righe prodotto dalla deal: non si passa una
lista di articoli alla creazione, ma `dealId` + `templateId`.

<Steps>
<Step>
Elenca i template di tipo `QUOTE` (`GET /document-templates?type=QUOTE`) e
scegline uno.
</Step>
<Step>
Crea il preventivo con `POST /quotes` passando `dealId` e `templateId`
(opzionalmente `clauseIds` ed `expiresAt`).
</Step>
<Step>
Invialo con `POST /quotes/{id}/send`: Audin genera il documento e lo recapita al
contatto della deal.
</Step>
</Steps>

<Tabs items={["curl", "JavaScript"]}>
<Tab value="curl">

```bash
BASE="https://api.audin.ai"

# 1. Scegli un template QUOTE (la lista è paginata: { templates, total, … })
TEMPLATE_ID=$(curl -s "$BASE/document-templates?type=QUOTE" \
  -H "X-API-Key: $API_KEY" | jq -r '.templates[0].id')

# 2. Crea il preventivo dalla deal
QUOTE_ID=$(curl -sX POST $BASE/quotes \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"dealId\":\"<deal-id>\",\"templateId\":\"$TEMPLATE_ID\"}" \
  | jq -r '.id')

# 3. Invialo al cliente
curl -X POST "$BASE/quotes/$QUOTE_ID/send" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'
```

</Tab>
<Tab value="JavaScript">

```js
const BASE = "https://api.audin.ai";
const headers = {
  "X-API-Key": process.env.AUDIN_API_KEY,
  "Content-Type": "application/json",
};

// 1. Scegli un template QUOTE (la lista è paginata: { templates, total, … })
const templates = await (
  await fetch(`${BASE}/document-templates?type=QUOTE`, { headers })
).json();
const templateId = templates.templates[0].id;

// 2. Crea il preventivo dalla deal
const quote = await (
  await fetch(`${BASE}/quotes`, {
    method: "POST",
    headers,
    body: JSON.stringify({ dealId, templateId }),
  })
).json();

// 3. Invialo al cliente
await fetch(`${BASE}/quotes/${quote.id}/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({}),
});
```

</Tab>
</Tabs>

<Callout type="info">
  Lo stato di un preventivo (`DRAFT`, `SENT`, `VIEWED`, `ACCEPTED`, `REJECTED`,
  `EXPIRED`) si legge con `GET /quotes/{id}`. Vedi
  [Documenti](/docs/api-rest/documenti).
</Callout>

## Flusso 3 — Tracking della firma di un contratto

Obiettivo: inviare un **contratto** per la firma e seguirne l'evoluzione fino a
uno stato finale. Non esistono webhook: lo stato si segue con **polling**
periodico di `GET /contracts/{id}`, leggendo il campo `.status`.

Gli stati di un contratto:

| Stato | Significato |
|-------|-------------|
| `DRAFT` | Bozza, non ancora inviato |
| `SENT` | Inviato al firmatario |
| `VIEWED` | Visualizzato dal firmatario |
| `SIGNED` | Firmato (stato finale positivo) |
| `REJECTED` | Rifiutato dal firmatario |
| `EXPIRED` | Scaduto senza firma |

<Steps>
<Step>
Crea il contratto con `POST /contracts` (`dealId` + `templateId`).
</Step>
<Step>
Invialo per la firma con `POST /contracts/{id}/send`.
</Step>
<Step>
Esegui il **polling** di `GET /contracts/{id}` a intervalli regolari, leggendo
`.status`, finché non raggiungi uno stato finale (`SIGNED`, `REJECTED`,
`EXPIRED`).
</Step>
</Steps>

<Tabs items={["curl", "JavaScript"]}>
<Tab value="curl">

```bash
BASE="https://api.audin.ai"

# 1. Crea e 2. invia il contratto per la firma
CONTRACT_ID=$(curl -sX POST $BASE/contracts \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dealId":"<deal-id>","templateId":"<contract-template-id>"}' \
  | jq -r '.id')

curl -X POST "$BASE/contracts/$CONTRACT_ID/send" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

# 3. Polling dello stato (no webhook)
while true; do
  STATUS=$(curl -s "$BASE/contracts/$CONTRACT_ID" \
    -H "X-API-Key: $API_KEY" | jq -r '.status')
  echo "[$(date)] Status: $STATUS"

  case "$STATUS" in
    SIGNED|REJECTED|EXPIRED)
      echo "Stato finale raggiunto: $STATUS"
      break
      ;;
  esac

  sleep 60
done
```

</Tab>
<Tab value="JavaScript">

```js
const BASE = "https://api.audin.ai";
const headers = {
  "X-API-Key": process.env.AUDIN_API_KEY,
  "Content-Type": "application/json",
};

// 1. Crea e 2. invia il contratto per la firma
const contract = await (
  await fetch(`${BASE}/contracts`, {
    method: "POST",
    headers,
    body: JSON.stringify({ dealId, templateId: contractTemplateId }),
  })
).json();

await fetch(`${BASE}/contracts/${contract.id}/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({}),
});

// 3. Polling dello stato (no webhook)
const FINAL = new Set(["SIGNED", "REJECTED", "EXPIRED"]);

async function pollStatus() {
  while (true) {
    const current = await (
      await fetch(`${BASE}/contracts/${contract.id}`, {
        headers: { "X-API-Key": process.env.AUDIN_API_KEY },
      })
    ).json();

    if (FINAL.has(current.status)) return current.status;
    await new Promise((r) => setTimeout(r, 60_000)); // attendi 60s
  }
}

const finalStatus = await pollStatus();
```

</Tab>
</Tabs>

<Callout type="warn">
  L'API è **polling-only**: non ci sono webhook. Per gli stati che evolvono nel
  tempo (firma di un contratto, accettazione di un preventivo) interroga la
  risorsa a intervalli regolari (es. ogni 60s). Tieni conto del
  [rate limit](/docs/api-rest/idempotency-e-rate-limit) (100 req/min per API
  Key) quando scegli la frequenza di polling.
</Callout>

## Prossimo passo

<Cards>
  <Card href="/docs/api-rest/errori" title="Errori & deprecati" description="Glossario dei codici di errore e migrazione dagli endpoint legacy." />
  <Card href="/docs/api-rest/documenti" title="Documenti" description="Dettaglio di preventivi e contratti: campi, stati e operazioni." />
</Cards>
