---
title: Documenti
description: Prodotti, categorie, clausole, template documento, preventivi e contratti — genera e traccia i documenti commerciali con l'API REST partner.
---

Il gruppo **Documenti** copre il ciclo dei documenti commerciali: il **catalogo
prodotti** e le sue **categorie**, le **clausole** riutilizzabili, i **template
documento** da cui generare **preventivi** (quote) e **contratti**, con il
tracking del loro stato di invio e firma.

## Le risorse

| Path | Descrizione |
|------|-------------|
| `/products` | Catalogo prodotti / servizi |
| `/product-categories` | Categorie di prodotto |
| `/clauses` | Clausole riutilizzabili per i documenti |
| `/document-templates` | Template per preventivi e contratti (`type` `QUOTE` o `CONTRACT`) |
| `/quotes` | Preventivi — crea, invia, traccia stato |
| `/contracts` | Contratti — crea, invia per firma, traccia stato |

Tutte le rotte richiedono l'header `X-API-Key`. Lo schema completo resta sullo
[Swagger](https://api.audin.ai/docs/partners).

## Catalogo: prodotti, categorie, clausole

Il **prodotto** (`name` obbligatorio, più `categoryId`, `sku`, `oneTimePrice`,
`recurringPrice`, `billingPeriod`, `currency`, …) alimenta sia le righe prodotto
delle deal sia i documenti. Le **categorie** (`/product-categories`) li
raggruppano; le **clausole** (`/clauses`, con `name` e `content`) sono blocchi di
testo riutilizzabili nei documenti.

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

```bash
curl -X POST https://api.audin.ai/products \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Licenza Pro",
    "recurringPrice": 49,
    "billingPeriod": "MONTH",
    "currency": "EUR"
  }'
```

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

```js
const res = await fetch("https://api.audin.ai/products", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.AUDIN_API_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Licenza Pro",
    recurringPrice: 49,
    billingPeriod: "MONTH",
    currency: "EUR",
  }),
});
const product = await res.json();
```

</Tab>
</Tabs>

Ognuna di queste risorse offre le operazioni CRUD standard
(`GET`/`POST` sulla collezione, `GET`/`PUT`/`DELETE` sul singolo `id`).

## Template documento

Un **template documento** (`/document-templates`) ha un `type` (`QUOTE` o
`CONTRACT`), un `htmlContent` e, opzionalmente, `defaultClauseIds`. È il punto di
partenza per generare preventivi e contratti. Filtra per tipo con `?type=QUOTE`:

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

```bash
curl "https://api.audin.ai/document-templates?type=QUOTE" \
  -H "X-API-Key: $API_KEY"
```

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

```js
const res = await fetch(
  "https://api.audin.ai/document-templates?type=QUOTE",
  { headers: { "X-API-Key": process.env.AUDIN_API_KEY } },
);
// la lista è paginata: { templates, total, currentPage, totalPages, pageSize }
const { templates } = await res.json();
```

</Tab>
</Tabs>

## Preventivi (quote)

Un **preventivo** si crea a partire da una **deal** e da un **template**. I campi
chiave alla creazione:

| Campo | Tipo | Obbligatorio | Note |
|-------|------|:---:|------|
| `dealId` | string | sì | Deal di riferimento (eredita le righe prodotto) |
| `templateId` | string | sì | Template `QUOTE` da cui generare il documento |
| `clauseIds` | string[] | no | Clausole da includere |
| `expiresAt` | string | no | Scadenza del preventivo (ISO-8601) |

Il ciclo di vita di un preventivo passa per gli stati `DRAFT`, `SENT`,
`VIEWED`, `ACCEPTED`, `REJECTED`, `EXPIRED`.

### Crea un preventivo da template e invialo

<Steps>
<Step>
Recupera il template `QUOTE` desiderato (`GET /document-templates?type=QUOTE`).
</Step>
<Step>
Crea il preventivo con `POST /quotes` passando `dealId` e `templateId`.
</Step>
<Step>
Invialo con `POST /quotes/{id}/send` (genera il documento e lo recapita al
contatto della deal).
</Step>
<Step>
Traccia lo stato con `GET /quotes/{id}` ed eventualmente `GET /quotes/{id}/events`.
</Step>
</Steps>

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

```bash
# 1. Crea il preventivo dalla deal
QUOTE_ID=$(curl -sX POST https://api.audin.ai/quotes \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"dealId":"<deal-id>","templateId":"<template-id>"}' \
  | jq -r '.id')

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

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

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

// 1. Crea il preventivo dalla deal
const quote = await (
  await fetch("https://api.audin.ai/quotes", {
    method: "POST",
    headers,
    body: JSON.stringify({ dealId, templateId }),
  })
).json();

// 2. Invialo al cliente
await fetch(`https://api.audin.ai/quotes/${quote.id}/send`, {
  method: "POST",
  headers,
  body: JSON.stringify({}),
});
```

</Tab>
</Tabs>

## Contratti

Un **contratto** si crea come un preventivo (`dealId` + `templateId`,
opzionalmente `quoteId` per derivarlo da un preventivo accettato, `clauseIds`,
`expiresAt`) e si **invia per la firma** con `POST /contracts/{id}/send`.

Lo **stato** del contratto evolve nel tempo e si segue con polling di
`GET /contracts/{id}` (campo `status`) — non esistono webhook. Gli stati
possibili:

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

Lo storico degli eventi del documento è disponibile su
`GET /contracts/{id}/events`. Altre operazioni: `POST /contracts/{id}/generate-pdf`
e `POST /contracts/{id}/revoke-link`.

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

```bash
# Crea e invia un contratto per la firma
CONTRACT_ID=$(curl -sX POST https://api.audin.ai/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 "https://api.audin.ai/contracts/$CONTRACT_ID/send" \
  -H "X-API-Key: $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

# Polling dello stato
curl "https://api.audin.ai/contracts/$CONTRACT_ID" \
  -H "X-API-Key: $API_KEY" | jq -r '.status'
```

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

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

const contract = await (
  await fetch("https://api.audin.ai/contracts", {
    method: "POST",
    headers,
    body: JSON.stringify({ dealId, templateId: contractTemplateId }),
  })
).json();

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

// Polling dello stato (no webhook)
const current = await (
  await fetch(`https://api.audin.ai/contracts/${contract.id}`, {
    headers: { "X-API-Key": process.env.AUDIN_API_KEY },
  })
).json();
console.log(current.status); // DRAFT | SENT | VIEWED | SIGNED | REJECTED | EXPIRED
```

</Tab>
</Tabs>

<Callout type="info">
  Gli stati che evolvono nel tempo (preventivo aperto/accettato, contratto
  firmato) si seguono con **polling** periodico della risorsa: l'API è
  **polling-only**, senza webhook. Vedi
  [Flussi operativi](/docs/api-rest/flussi).
</Callout>

<Callout type="info">
  Schema completo (tutti i campi e parametri):
  [Swagger](https://api.audin.ai/docs/partners).
</Callout>

## Prossimo passo

<Cards>
  <Card href="/docs/api-rest/flussi" title="Flussi operativi" description="Invio preventivo e tracking firma contratto end-to-end." />
  <Card href="/docs/api-rest/messaging-email" title="Messaging & email" description="Notifica il cliente via WhatsApp/SMS o controlla lo stato delle email." />
</Cards>
