# API

Una chiamata in uscita dal suo sistema — un evento CRM, un modulo, un callback chiamata persa. Una lista su un programma è [Campagne](https://docs.voicelogica.ai/outbound-calls/campaigns/), non questo endpoint.

Le impostazioni [In uscita](https://docs.voicelogica.ai/outbound-calls/outgoing/) dell'agent si applicano ancora. Questa richiesta sceglie il numero, l'agent, e contesto extra opzionale per *questa* chiamata.

## Prima di chiamare

1. Il piano include **Allow Outbound Calls**.
2. [Chiave API](https://docs.voicelogica.ai/it/getting-started/api-keys/) con il gruppo **Calls**.
3. Un trunk (o telefono VoIP) da cui chiamare — [Il suo proprio operatore](https://docs.voicelogica.ai/telephony/your-own-carrier/) / [Numeri Voice Logica](https://docs.voicelogica.ai/telephony/voice-logica-numbers/).
4. L'**agent id** — dall'URL agent su **My Agents**, o **Copy** su una riga campagna.

## Prima configurazione — una chiamata, poi Calls

```
POST https://api.voicelogica.ai/api/v1/phones/calls/initiate-call
```

```http
x-api-key: YOUR_API_KEY
Content-Type: application/json
```

Rivenditori: `x-company-id` opzionale per agire su una sussidiaria. Senza di esso, viene usata l'azienda propria della chiave.

Invii **`destinationNumber`** e **`agentId`**. Invii **`sipTrunkId`** o **`voipPhoneId`** a meno che l'azienda non abbia già una route in uscita / trunk default che può portare la chiamata — se nessuno è inviato e nessun trunk può essere risolto, l'API restituisce che nessun SIP trunk o telefono VoIP attivo è stato specificato.

**Trunk (usuale):**

```bash
curl -X POST https://api.voicelogica.ai/api/v1/phones/calls/initiate-call \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "sipTrunkId": "your_sip_trunk_id",
    "destinationNumber": "+14155552671",
    "agentId": "your_agent_id"
  }'
```

**VoIP phone id** funziona ancora — il server lo risolve a un trunk.

Il successo è `{ "callId": "..." }`. Se la destinazione è fuori 09:00–21:00 ora locale, può ottenere `"scheduled": true` più `scheduleTime` e `reason`. Apra **Calls** e ascolti.

`destinationNumber` in E.164 (`+14155552671`).

## Cosa può inviare

**Richiesto per una chiamata IA in uscita**

| Campo | Cosa fa |
|-------|----------------|
| `destinationNumber` | Numero da chiamare. |
| `agentId` | Agent che parla. Richiesto per uscita IA; opzionale solo per `isInternalCall`. |

**Fonte chiamata — ne invii uno, o si affidi al default uscita aziendale**

| Campo | Cosa fa |
|-------|----------------|
| `sipTrunkId` | Trunk da **Telephony → Trunks**. Lo preferisca. |
| `voipPhoneId` | ID linea legacy. Risolto a un trunk. |
| `callerId` | E.164 o SIP URI mostrato al destinatario. Deve essere un numero che quel trunk può presentare. |

**Solo questa chiamata**

| Campo | Cosa fa |
|-------|----------------|
| `contextForAi` | Aggiunto al system prompt per questa chiamata. |
| `dynamicVariables` | Coppie chiave/valore stringa che il prompt può usare (`{{customer_name}}`). |
| `superVariables` | Valori tipizzati: `{ placeholder, value, type }` — `text` / `number` / `boolean` / `date` / `time`. |
| `metadata` | Il suo tracking. Memorizzato sulla chiamata. Chiavi che iniziano `scenario_` sono strippate. |
| `emailAddress` | Dove inviare il riepilogo / registrazione. |
| `welcomeMessageOverride` | Parlato invece del saluto agent. |
| `isWelcomeMessageAIGenerated` | L'IA scrive il saluto per questa chiamata. |
| `scheduledAt` | Data ISO. Chiamare più tardi invece di ora. |
| `maxRetries` | 1–3 se occupato / nessuna risposta / casella vocale. Default 3. |
| `retryDelayMinutes` | 30–1440. Default 30. |
| `additionalPhoneNumbers` | Numeri extra sulla stessa richiesta. |

Non invii `fromNumber`. Il contratto pubblico è `sipTrunkId` / `voipPhoneId`.

## Protezioni (solo uscita)

L'entrata non è mai limitata.

- **Time** (attivo) — 09:00–21:00 nell'ora locale del paese *destinazione*. Fuori quello, la chiamata è bloccata o programmata. Bypass: `overrideTimeRestriction: true`.
- **Day** (attivo) — weekend / festivi possono essere bloccati per paese destinazione. Bypass: `overrideDayRestriction: true`.
- **Anti-molestia** (spento a meno che non invii `useAntiHarassmentProtection: true`) — max 3 chiamate riuscite e 3 fallite per numero al giorno, 1 ora tra chiamate riuscite, max 5 riuscite per settimana, nessuna chiamata attiva/programmata duplicata. **Allowed test numbers** della campagna bypassano questo.

Bypassare regole di tempo o giorno può violare la legge locale. Attivi anti-molestia per qualsiasi lavoro di contatto ripetuto.

## Se fallisce

Il corpo è `{ "error": "<code>", "reason": "<message>" }`.

| Codice | Significato |
|------|---------|
| `call_already_in_progress` | Una chiamata live o programmata a questo numero esiste già. |
| `agent_not_found` / `voip_phone_not_found` | ID errato. |
| `daily_call_limit_reached` | 3 chiamate riuscite a questo numero oggi (anti-molestia). |
| `failed_call_limit_reached` | 3 tentativi falliti oggi. |
| `cooldown_period_active` | Attenda 1 ora dopo una chiamata riuscita a questo numero. |
| `weekly_call_limit_reached` | 5 chiamate riuscite questa settimana. |
| `call_already_scheduled` / `failed_to_schedule_call` | Conflitto programma. |
| `callee_opted_out` | Questo numero ha chiesto di non essere chiamato di nuovo. |
| `insufficient_credits` / `no_seconds_available` / `no_channels_available` / `no_concurrent_calls_available` | Piano / crediti. |
| `maximum_authentication_attempts_exceeded` | Telefono disattivato dopo ripetuti fallimenti auth. |

402 è fatturazione. 400 è una richiesta errata o una protezione. 500 è il server chiamate — riprovi più tardi.

## Esempio

```typescript
const response = await fetch('https://api.voicelogica.ai/api/v1/phones/calls/initiate-call', {
  method: 'POST',
  headers: { 'x-api-key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    destinationNumber: '+14155552671',
    agentId: 'your_agent_id',
    sipTrunkId: 'your_sip_trunk_id',
    contextForAi: 'Customer asked about order ORD123',
    dynamicVariables: { customer_name: 'Ada', order_id: 'ORD123' },
    useAntiHarassmentProtection: true,
  }),
});
const result = await response.json();
if (result.callId) console.log(result.callId);
else console.error(result.error, result.reason);
```

Programma + riprovi:

```json
{
  "destinationNumber": "+14155552671",
  "agentId": "your_agent_id",
  "sipTrunkId": "your_sip_trunk_id",
  "scheduledAt": "2026-09-16T14:30:00Z",
  "maxRetries": 2,
  "retryDelayMinutes": 120
}
```

`scheduledAt` è convertito alla zona del paese destinazione. Le protezioni si applicano ancora a meno che non le sovrascriva.

## Come appare "rotto"

- 400 "no active SIP trunk" — invii `sipTrunkId`, o aggiunga un trunk con numeri e un default in uscita.
- `scheduled: true` quando si aspettava ora — l'ora locale destinazione è fuori 09:00–21:00.
- L'agent parla sopra "ciao" — [In uscita](https://docs.voicelogica.ai/outbound-calls/outgoing/) **Who speaks first**, non questo payload.
- Chiamata mancante su **Calls** — azienda sbagliata (`x-company-id`), o la richiesta non ha mai restituito un `callId`.

## Risoluzione dei problemi

**fromNumber funzionava**

Il corpo pubblico è `sipTrunkId` o `voipPhoneId`. Invii il trunk id da **Telephony → Trunks**.

**Ho postato ora e ottenuto scheduled: true**

Restrizione tempo o giorno. Attenda la finestra, o imposti `overrideTimeRestriction` / `overrideDayRestriction` solo se le è permesso.

## Sta costruendo qualcosa?

Scriva [developers@voicelogica.ai](mailto:developers@voicelogica.ai) — crediti test extra e aiuto sull'integrazione.

- RIFERIMENTO API [api.voicelogica.ai/api-docs](https://api.voicelogica.ai/api-docs)
- DEVELOPERS [developers@voicelogica.ai](mailto:developers@voicelogica.ai)
- SUPPORTO [support@voicelogica.ai](mailto:support@voicelogica.ai)
