Vai al contenuto

Guida all’API di Nexyzen

Hai crediti che aspetti di incassare e fatture che devi ancora pagare. Nexyzen, la piattaforma di Camera di Compensazione, cerca catene di debiti reciproci tra imprese e le chiude per compensazione, senza bonifici. Tu cedi un credito che vanti verso un tuo debitore, ricevi in cambio un credito equivalente da un altro partecipante, e il tuo debito si estingue. Nessun denaro si muove.

Questa guida spiega come collegare il tuo gestionale alla piattaforma via API: inviare le fatture, leggere le compensazioni che il motore propone, accettarle e recuperare l’atto di cessione del credito. Gli esempi sono in Java, PHP, C# e Python.

La documentazione interattiva, con cui provare le chiamate dal browser, è su cameracompensazione.github.io/cc_webservice.

Come è fatta l’API

C’è un solo indirizzo:

POST https://webapp.cameracompensazione.it/webservices/Content-Type: application/json

Ogni richiesta è un oggetto JSON con un campo op che dice quale operazione vuoi, il token di sessione jwt e un oggetto dati con i parametri:

{ "op": "nome_operazione", "jwt": "…", "dati": { } }

Le operazioni disponibili:

opCosa fa
gjwtapre la sessione e restituisce il token JWT
cjwtverifica che un JWT sia ancora valido
ins_manualeinvia una fattura inserendone i dati a mano
ins_datiinvia una fattura elettronica (XML, P7M o PDF)
get_compensazionilegge le compensazioni proposte per una P.IVA
accetta_compensazioneaccetta una compensazione
get_lettere_cessionerecupera gli atti di cessione del credito

Le risposte hanno sempre un campo result. Quando qualcosa va storto, result vale errore e message spiega il motivo. I codici HTTP seguono la convenzione usuale: 400 richiesta malformata, 401 non autorizzato, 422 dati non elaborabili, 503 servizio momentaneamente occupato.

Il ciclo di vita di una compensazione

Prima di scrivere codice, tieni presente il flusso, perché una parte non è istantanea.

  1. Invii le fatture. Carichi crediti e debiti della tua azienda.
  2. Il motore elabora. Periodicamente, il motore di clearing proprietario cerca nei dati i cicli di debiti reciproci che si possono chiudere. Non gira a ogni chiamata: le compensazioni compaiono dopo l’elaborazione successiva. Durante l’elaborazione il webservice risponde 503; riprovi più tardi.
  3. Leggi le proposte. Con get_compensazioni vedi le compensazioni in attesa della tua accettazione.
  4. Accetti. Con accetta_compensazione confermi. Quando tutti i partecipanti del ciclo hanno accettato, il ciclo si perfeziona.
  5. Ricevi l’atto. Con get_lettere_cessione recuperi l’atto di cessione del credito, che formalizza l’operazione.

Autenticazione

Per ottenere le credenziali (un cod_affiliato e un token) scrivi a commerciale@cameracompensazione.it. Sono le credenziali dell’integrazione, non di una singola azienda.

La sessione si apre con gjwt. Ricevi un JWT valido un’ora, da mettere nel campo jwt di ogni chiamata successiva.

{
  "op": "gjwt",
  "criptato": false,
  "dati": { "cod_affiliato": "il_tuo_codice", "token": "il_tuo_token" }
}

Risposta:

{ "result": "Successful login", "jwt": "eyJ0eXAiOiJKV1Q…", "expireAt": 1788779798 }

token_azienda: l’autorizzazione sulla singola P.IVA

Le operazioni che leggono o modificano le compensazioni di un’azienda (get_compensazioni, accetta_compensazione, get_lettere_cessione) richiedono una prova che tu agisca per conto di quella P.IVA. La prova è il token_azienda, che il webservice ti restituisce la prima volta che invii una fattura per quell’azienda. Conservalo: lo passi nelle chiamate successive.

In alternativa leghi il JWT a una singola P.IVA fin dalla connessione, aggiungendo partita_iva e token_azienda ai dati di gjwt. Il JWT che ottieni vale solo per quell’azienda, e non devi più ripetere il token_azienda a ogni chiamata.

Inviare le fatture

Con ins_manuale invii una fattura passandone i campi. tipo_fattura vale v per una vendita (un tuo credito) o a per un acquisto (un tuo debito). Se ometti importo_residuo, o lo metti a zero, vale l’intero importo.

{
  "op": "ins_manuale",
  "jwt": "…",
  "dati": {
    "tipo_fattura": "v",
    "partita_iva_creditore": "IT01234567897",
    "partita_iva_debitore":  "IT09876543210",
    "data_fattura": "2026-09-01",
    "numero_fattura": "2026/145",
    "importo_totale": "1200.00"
  }
}

Risposta:

{ "result": "ok", "inserted": [845], "token_azienda": "d4b8d6b5ebbf8923108f857e2849e874" }

Quel token_azienda è la chiave d’accesso alle compensazioni del proponente. Salvalo.

Se hai già la fattura elettronica, usa ins_dati: passi il file in base64 nel campo documento_base64 e il webservice ne estrae i dati. Accetta XML e P7M (che legge direttamente) e PDF (che mette in coda per la verifica manuale).

Leggere le compensazioni proposte

get_compensazioni restituisce le compensazioni in cui la tua azienda è cedente e che aspettano la tua accettazione.

{
  "op": "get_compensazioni",
  "jwt": "…",
  "dati": { "partita_iva": "IT01234567897", "token_azienda": "d4b8d6b5…", "lingua": "it" }
}

Ogni elemento della risposta descrive l’operazione per intero: quale credito cedi e verso chi, quale tuo debito si compensa, a chi va il credito ceduto e da chi ricevi la contropartita. C’è anche il token monouso che ti serve per accettare, e anagrafica_mancante, l’elenco dei campi anagrafici che devi completare prima di poter accettare (di norma i dati del legale rappresentante, necessari all’atto di cessione).

{
  "result": "ok",
  "compensazioni": [{
    "id_compensazione": 92,
    "id_ciclo": 2927,
    "importo": 1000,
    "token": "JqCSY_ycKSvQdohe9yJgJYyuX0dbbAO4",
    "anagrafica_mancante": ["nome_legale_rappresentante", "cognome_legale_rappresentante"],
    "credito_verso":       { "partita_iva": "IT099…", "ragione_sociale": "Beta S.p.A." },
    "debito_verso":        { "partita_iva": "IT033…", "ragione_sociale": "Gamma S.r.l." },
    "credito_ceduto_a":    { "partita_iva": "IT055…", "ragione_sociale": "Delta S.n.c." },
    "credito_ricevuto_da": { "partita_iva": "IT077…", "ragione_sociale": "Epsilon S.r.l." },
    "base_legale": "compensazione volontaria ex art. 1252 c.c."
  }]
}

Accettare una compensazione

Qui sta la parte che richiede attenzione. Accettare non è un clic: cedi un credito a un terzo, e la legge chiede che tu dichiari e garantisca alcune cose su quel credito. L’API le pretende come le pretende il modulo web pubblico. Passi un oggetto dichiarazioni con undici conferme, tutte a true. Se ne manca una, la risposta è 422 e l’accettazione non passa.

Le undici conferme:

CampoChe cosa dichiari
riconoscimento_creditovanti il credito verso il tuo debitore
riconoscimento_debitohai il debito che viene compensato
cessione_creditocedi il credito al cessionario
ricezione_creditoaccetti il credito ricevuto in cambio
dich_esistenzail credito esiste, è certo, valido ed esigibile
dich_titolaritail credito è tuo e non è vincolato a favore di terzi
dich_non_pagatoil credito non è stato pagato o estinto
dich_non_contestatoil credito non è contestato né in causa
dich_no_procedurenon sei in procedura concorsuale né insolvente
dich_no_incedibilitala cessione non viola divieti o vincoli
dich_pro_solutoprendi atto delle condizioni (cessione pro soluto)

Se get_compensazioni ti ha restituito anagrafica_mancante non vuoto, aggiungi anche l’oggetto anagrafica con i campi mancanti. Le date vanno in formato AAAA-MM-GG.

{
  "op": "accetta_compensazione",
  "jwt": "…",
  "dati": {
    "token": "JqCSY_ycKSvQdohe9yJgJYyuX0dbbAO4",
    "token_azienda": "d4b8d6b5…",
    "anagrafica": {
      "nome_legale_rappresentante": "Anna",
      "cognome_legale_rappresentante": "Rossi",
      "cf_legale_rappresentante": "RSSNNA80A41F158X",
      "qualita_legale_rappresentante": "Amministratore Unico",
      "luogo_nascita_legale_rappresentante": "Messina",
      "data_nascita_legale_rappresentante": "1980-01-01"
    },
    "dichiarazioni": {
      "riconoscimento_credito": true, "riconoscimento_debito": true,
      "cessione_credito": true, "ricezione_credito": true,
      "dich_esistenza": true, "dich_titolarita": true, "dich_non_pagato": true,
      "dich_non_contestato": true, "dich_no_procedure": true,
      "dich_no_incedibilita": true, "dich_pro_soluto": true
    }
  }
}

Risposta:

{ "result": "ok", "accepted": true, "id_compensazione": 92, "id_ciclo": 2927, "ciclo_completo": false }

ciclo_completo diventa true quando la tua accettazione è l’ultima che mancava: da quel momento il ciclo si perfeziona e gli atti partono.

Recuperare l’atto di cessione

Perfezionato il ciclo, get_lettere_cessione restituisce l’atto di cessione del credito per la tua azienda, già compilato e pronto in HTML. È lo stesso documento che la piattaforma notifica via PEC al debitore ceduto.

{
  "op": "get_lettere_cessione",
  "jwt": "…",
  "dati": { "partita_iva": "IT01234567897", "token_azienda": "d4b8d6b5…", "tutte": false }
}

Con tutte: false ricevi solo gli atti nuovi e li marchi come consegnati; con tutte: true rileggi anche quelli già ritirati.

Stati ed errori da gestire

Tre casi meritano codice apposta:

  • 503 durante l’elaborazione. Mentre il motore cerca i cicli, il webservice rifiuta le nuove richieste. Riprova dopo qualche minuto invece di considerarlo un errore.
  • 401 sul token_azienda. Se leggi o accetti compensazioni senza il token_azienda giusto (o senza un JWT legato alla P.IVA), ottieni 401. Verifica di aver salvato il token restituito al primo invio fattura.
  • 422 sulle dichiarazioni o sull’anagrafica. Manca una conferma o un campo obbligatorio. Il message elenca cosa manca.

Scenari reali

Il gestionale che invia le fatture da solo. Un ERP come Odoo o SAP, a fine giornata, prende le fatture emesse e ricevute e le manda con ins_manuale o ins_dati. Alla prossima elaborazione, un job legge con get_compensazioni le proposte e le mostra all’amministrazione, che accetta con un clic. L’integrazione conserva un token_azienda per ogni azienda gestita.

La banca che mostra la liquidità nascosta. Una fintech o una banca d’impresa (Qonto integra la piattaforma con questa logica) legge le fatture non pagate del cliente, le invia, e quando compare una compensazione la propone dentro l’home banking come modo per liberare capitale circolante senza chiedere credito. L’atto di cessione recuperato con get_lettere_cessione diventa l’allegato dell’operazione.

Il portale pubblico. Un frontend che gira nel browser dell’utente non può custodire le credenziali dell’integrazione. Per questo gjwt accetta anche un payload cifrato (criptato: true), con cui il frontend ottiene un JWT a vita breve senza esporre il token. Lo usa il sito pubblico di Nexyzen.

Esempi completi

Ogni esempio fa lo stesso giro: apre la sessione, invia una fattura di vendita, legge le compensazioni e ne accetta una con le dichiarazioni. Cambia solo il linguaggio.

Java

import java.net.URI;
import java.net.http.*;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

public class NexyzenClient {
    static final String URL = "https://webapp.cameracompensazione.it/webservices/";
    static final HttpClient http = HttpClient.newHttpClient();
    static final ObjectMapper json = new ObjectMapper();

    static JsonNode call(Map<String,Object> body) throws Exception {
        HttpRequest req = HttpRequest.newBuilder(URI.create(URL))
            .header("Content-Type", "application/json")
            .POST(HttpRequest.BodyPublishers.ofString(json.writeValueAsString(body)))
            .build();
        return json.readTree(http.send(req, HttpResponse.BodyHandlers.ofString()).body());
    }

    static Map<String,Boolean> dichiarazioni() {
        String[] campi = {"riconoscimento_credito","riconoscimento_debito","cessione_credito",
            "ricezione_credito","dich_esistenza","dich_titolarita","dich_non_pagato",
            "dich_non_contestato","dich_no_procedure","dich_no_incedibilita","dich_pro_soluto"};
        var d = new java.util.HashMap<String,Boolean>();
        for (String c : campi) d.put(c, true);
        return d;
    }

    public static void main(String[] args) throws Exception {
        // 1. connessione
        JsonNode login = call(Map.of("op","gjwt","criptato",false,
            "dati", Map.of("cod_affiliato","IL_TUO_CODICE","token","IL_TUO_TOKEN")));
        String jwt = login.get("jwt").asText();

        // 2. invio di una fattura di vendita
        JsonNode ins = call(Map.of("op","ins_manuale","jwt",jwt,
            "dati", Map.of("tipo_fattura","v",
                "partita_iva_creditore","IT01234567897",
                "partita_iva_debitore","IT09876543210",
                "data_fattura","2026-09-01","numero_fattura","2026/145",
                "importo_totale","1200.00")));
        String tokenAzienda = ins.get("token_azienda").asText();

        // 3. lettura delle compensazioni proposte
        JsonNode comp = call(Map.of("op","get_compensazioni","jwt",jwt,
            "dati", Map.of("partita_iva","IT01234567897","token_azienda",tokenAzienda)));
        if (!comp.has("compensazioni") || comp.get("compensazioni").isEmpty()) {
            System.out.println("Nessuna compensazione: riprova dopo l'elaborazione.");
            return;
        }

        // 4. accettazione della prima
        String token = comp.get("compensazioni").get(0).get("token").asText();
        JsonNode ok = call(Map.of("op","accetta_compensazione","jwt",jwt,
            "dati", Map.of("token",token,"token_azienda",tokenAzienda,
                "dichiarazioni", dichiarazioni())));
        System.out.println("accettata: " + ok.get("accepted") + ", ciclo completo: " + ok.get("ciclo_completo"));
    }
}

PHP

<?php
const URL = 'https://webapp.cameracompensazione.it/webservices/';

function call(array $body): array {
    $ch = curl_init(URL);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
        CURLOPT_POSTFIELDS => json_encode($body),
    ]);
    $resp = curl_exec($ch);
    curl_close($ch);
    return json_decode($resp, true);
}

function dichiarazioni(): array {
    $campi = ['riconoscimento_credito','riconoscimento_debito','cessione_credito',
        'ricezione_credito','dich_esistenza','dich_titolarita','dich_non_pagato',
        'dich_non_contestato','dich_no_procedure','dich_no_incedibilita','dich_pro_soluto'];
    return array_fill_keys($campi, true);
}

// 1. connessione
$login = call(['op'=>'gjwt','criptato'=>false,
    'dati'=>['cod_affiliato'=>'IL_TUO_CODICE','token'=>'IL_TUO_TOKEN']]);
$jwt = $login['jwt'];

// 2. invio di una fattura di vendita
$ins = call(['op'=>'ins_manuale','jwt'=>$jwt,'dati'=>[
    'tipo_fattura'=>'v',
    'partita_iva_creditore'=>'IT01234567897',
    'partita_iva_debitore'=>'IT09876543210',
    'data_fattura'=>'2026-09-01','numero_fattura'=>'2026/145',
    'importo_totale'=>'1200.00']]);
$tokenAzienda = $ins['token_azienda'];

// 3. lettura delle compensazioni proposte
$comp = call(['op'=>'get_compensazioni','jwt'=>$jwt,
    'dati'=>['partita_iva'=>'IT01234567897','token_azienda'=>$tokenAzienda]]);
if (empty($comp['compensazioni'])) {
    echo "Nessuna compensazione: riprova dopo l'elaborazione.\n";
    exit;
}

// 4. accettazione della prima
$token = $comp['compensazioni'][0]['token'];
$ok = call(['op'=>'accetta_compensazione','jwt'=>$jwt,'dati'=>[
    'token'=>$token,'token_azienda'=>$tokenAzienda,'dichiarazioni'=>dichiarazioni()]]);
echo "accettata: {$ok['accepted']}, ciclo completo: {$ok['ciclo_completo']}\n";

C#

using System.Net.Http;
using System.Text;
using System.Text.Json;

class NexyzenClient
{
    const string Url = "https://webapp.cameracompensazione.it/webservices/";
    static readonly HttpClient Http = new();

    static async Task<JsonElement> Call(object body)
    {
        var content = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
        var resp = await Http.PostAsync(Url, content);
        var text = await resp.Content.ReadAsStringAsync();
        return JsonDocument.Parse(text).RootElement;
    }

    static Dictionary<string, bool> Dichiarazioni()
    {
        string[] campi = { "riconoscimento_credito","riconoscimento_debito","cessione_credito",
            "ricezione_credito","dich_esistenza","dich_titolarita","dich_non_pagato",
            "dich_non_contestato","dich_no_procedure","dich_no_incedibilita","dich_pro_soluto" };
        return campi.ToDictionary(c => c, _ => true);
    }

    static async Task Main()
    {
        // 1. connessione
        var login = await Call(new { op = "gjwt", criptato = false,
            dati = new { cod_affiliato = "IL_TUO_CODICE", token = "IL_TUO_TOKEN" } });
        string jwt = login.GetProperty("jwt").GetString()!;

        // 2. invio di una fattura di vendita
        var ins = await Call(new { op = "ins_manuale", jwt, dati = new {
            tipo_fattura = "v",
            partita_iva_creditore = "IT01234567897",
            partita_iva_debitore = "IT09876543210",
            data_fattura = "2026-09-01", numero_fattura = "2026/145",
            importo_totale = "1200.00" } });
        string tokenAzienda = ins.GetProperty("token_azienda").GetString()!;

        // 3. lettura delle compensazioni proposte
        var comp = await Call(new { op = "get_compensazioni", jwt,
            dati = new { partita_iva = "IT01234567897", token_azienda = tokenAzienda } });
        var lista = comp.GetProperty("compensazioni");
        if (lista.GetArrayLength() == 0)
        {
            Console.WriteLine("Nessuna compensazione: riprova dopo l'elaborazione.");
            return;
        }

        // 4. accettazione della prima
        string token = lista[0].GetProperty("token").GetString()!;
        var ok = await Call(new { op = "accetta_compensazione", jwt, dati = new {
            token, token_azienda = tokenAzienda, dichiarazioni = Dichiarazioni() } });
        Console.WriteLine($"accettata: {ok.GetProperty("accepted")}, ciclo completo: {ok.GetProperty("ciclo_completo")}");
    }
}

Python

import requests

URL = "https://webapp.cameracompensazione.it/webservices/"

def call(body: dict) -> dict:
    return requests.post(URL, json=body, timeout=30).json()

def dichiarazioni() -> dict:
    campi = ["riconoscimento_credito", "riconoscimento_debito", "cessione_credito",
             "ricezione_credito", "dich_esistenza", "dich_titolarita", "dich_non_pagato",
             "dich_non_contestato", "dich_no_procedure", "dich_no_incedibilita", "dich_pro_soluto"]
    return {c: True for c in campi}

# 1. connessione
login = call({"op": "gjwt", "criptato": False,
              "dati": {"cod_affiliato": "IL_TUO_CODICE", "token": "IL_TUO_TOKEN"}})
jwt = login["jwt"]

# 2. invio di una fattura di vendita
ins = call({"op": "ins_manuale", "jwt": jwt, "dati": {
    "tipo_fattura": "v",
    "partita_iva_creditore": "IT01234567897",
    "partita_iva_debitore": "IT09876543210",
    "data_fattura": "2026-09-01", "numero_fattura": "2026/145",
    "importo_totale": "1200.00"}})
token_azienda = ins["token_azienda"]

# 3. lettura delle compensazioni proposte
comp = call({"op": "get_compensazioni", "jwt": jwt,
             "dati": {"partita_iva": "IT01234567897", "token_azienda": token_azienda}})
if not comp.get("compensazioni"):
    print("Nessuna compensazione: riprova dopo l'elaborazione.")
    raise SystemExit

# 4. accettazione della prima
token = comp["compensazioni"][0]["token"]
ok = call({"op": "accetta_compensazione", "jwt": jwt, "dati": {
    "token": token, "token_azienda": token_azienda, "dichiarazioni": dichiarazioni()}})
print("accettata:", ok["accepted"], "- ciclo completo:", ok["ciclo_completo"])

Da qui in poi

Con questi quattro passi copri l’integrazione completa. Prova prima le chiamate dalla documentazione interattiva, poi chiedi le credenziali a commerciale@cameracompensazione.it. Un consiglio pratico: gestisci il 503 con qualche tentativo distanziato, e salva il token_azienda di ogni azienda che segui, perché è la chiave di tutto ciò che riguarda le sue compensazioni.