{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://nexaisoftware.de/schemas/voice-agent-export.json",
  "title": "NexAI Voice Agent – Exportpaket",
  "description": "Struktur der Datei export.json im Exportpaket eines Voice Agents von NexAI (Datenverordnung (EU) 2023/2854: Register nach Art. 26 Buchst. b, Export nach Art. 30 Abs. 5). Enthalten sind die Inhalte und Einstellungen des Kunden, die Anrufdatensätze beim Plattformanbieter und die Verbindungsdatensätze der Telefonanlage, soweit noch gespeichert, und die Nutzungsnachweise. Nicht enthalten sind Prompts und Gesprächslogik von NexAI (Art. 30 Abs. 6), Konten und Zugänge von NexAI beim Plattformanbieter sowie Zugangsdaten. Anfragen, Termine und Gesprächsnotizen, die der Voice Agent in ein Zielsystem des Kunden schreibt (z. B. NexAI CRM), werden dort exportiert. Das Paket ist eine ZIP-Datei mit export.json, den Listen anrufe, verbindungen und nutzungsnachweise zusätzlich als anrufe.csv, verbindungen.csv und nutzungsnachweise.csv nach RFC 4180 (Spalten wie die Feldnamen hier, ohne die verschachtelten Felder) und, soweit beauftragt, den Tonaufzeichnungen im Ordner ton/. Zeichenkodierung UTF-8 (RFC 3629), JSON nach RFC 8259.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schema",
    "formatVersion",
    "exportiertAm",
    "kunde",
    "wissensbasis",
    "einstellungen",
    "anrufe",
    "verbindungen",
    "nutzungsnachweise"
  ],
  "properties": {
    "schema": {
      "const": "https://nexaisoftware.de/schemas/voice-agent-export.json"
    },
    "formatVersion": {
      "const": "1.0",
      "description": "Fassung dieses Formats."
    },
    "exportiertAm": {
      "type": "string",
      "format": "date-time",
      "description": "Zeitpunkt, zu dem NexAI dieses Paket erzeugt hat, nach RFC 3339."
    },
    "kunde": {
      "type": "string",
      "minLength": 1,
      "description": "Name des Kunden."
    },
    "wissensbasis": {
      "type": "object",
      "description": "Inhalte, die der Kunde geliefert hat, in der zuletzt verwendeten Fassung. Ein leerer Text oder eine leere Liste heißt: keine Angabe.",
      "additionalProperties": false,
      "required": [
        "firma",
        "leistungen",
        "preise",
        "standort",
        "oeffnungszeiten",
        "haeufigeFragen",
        "gespraechsziel",
        "weitereFakten"
      ],
      "properties": {
        "firma": {
          "type": "string",
          "description": "Name und kurze Beschreibung des Unternehmens."
        },
        "leistungen": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Leistungen, je Eintrag eine."
        },
        "preise": {
          "type": "string",
          "description": "Preisangaben, die der Voice Agent nennen darf. Leer: Er nennt keine Preise."
        },
        "standort": {
          "type": "string",
          "description": "Anschrift oder Ort."
        },
        "oeffnungszeiten": {
          "type": "string",
          "description": "Öffnungszeiten, wie der Voice Agent sie nennen darf (Freitext)."
        },
        "haeufigeFragen": {
          "type": "array",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "frage",
              "antwort"
            ],
            "properties": {
              "frage": {
                "type": "string"
              },
              "antwort": {
                "type": "string"
              }
            }
          }
        },
        "gespraechsziel": {
          "type": "string",
          "description": "Worauf der Voice Agent das Gespräch lenken soll, z. B. einen Termin oder einen Rückruf."
        },
        "weitereFakten": {
          "type": "string",
          "description": "Weitere Angaben des Kunden."
        }
      }
    },
    "einstellungen": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "rufnummern",
        "begruessung",
        "sprache",
        "befugnisse",
        "weiterleitungsziele",
        "zeitzone",
        "zielsysteme"
      ],
      "properties": {
        "rufnummern": {
          "type": "array",
          "description": "Rufnummern, unter denen der Voice Agent Anrufe annimmt.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "nummer"
            ],
            "properties": {
              "nummer": {
                "type": "string",
                "description": "Rufnummer im internationalen Format nach ITU-T E.164, z. B. +4979511234567.",
                "pattern": "^\\+[1-9][0-9]{1,14}$"
              },
              "bezeichnung": {
                "type": "string",
                "description": "z. B. Zentrale."
              }
            }
          }
        },
        "begruessung": {
          "type": "string",
          "description": "Erster Satz des Voice Agents im Gespräch."
        },
        "sprache": {
          "type": "string",
          "description": "Sprache des Gesprächs nach BCP 47 (RFC 5646), z. B. de-DE.",
          "pattern": "^[a-z]{2,3}(-[A-Z]{2})?$"
        },
        "befugnisse": {
          "type": "object",
          "description": "Was der Voice Agent tun darf.",
          "additionalProperties": false,
          "required": [
            "termineVorschlagen",
            "termineBuchen",
            "rueckrufAufnehmen",
            "anfragenSpeichern",
            "weiterleiten"
          ],
          "properties": {
            "termineVorschlagen": {
              "type": "boolean",
              "description": "Freie Termine aus dem verknüpften Kalender nennen."
            },
            "termineBuchen": {
              "type": "boolean",
              "description": "Einen bestätigten Termin verbindlich eintragen."
            },
            "rueckrufAufnehmen": {
              "type": "boolean",
              "description": "Einen Rückrufwunsch aufnehmen und weitergeben."
            },
            "anfragenSpeichern": {
              "type": "boolean",
              "description": "Anfragen ohne Termin im Zielsystem ablegen."
            },
            "weiterleiten": {
              "type": "boolean",
              "description": "Anrufe an die Weiterleitungsziele übergeben."
            }
          }
        },
        "weiterleitungsziele": {
          "type": "array",
          "description": "Ziele, an die der Voice Agent Anrufe übergibt.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "bezeichnung",
              "ziel"
            ],
            "properties": {
              "bezeichnung": {
                "type": "string",
                "description": "z. B. Verkauf, Service."
              },
              "ziel": {
                "type": "string",
                "description": "Rufnummer nach E.164 oder interne Durchwahl der Telefonanlage des Kunden."
              },
              "wann": {
                "type": "string",
                "description": "Wofür der Voice Agent an dieses Ziel übergibt (Freitext)."
              },
              "erreichbarkeit": {
                "type": "array",
                "description": "Zeiten, zu denen das Ziel erreichbar ist, je Wochentag. Fehlende Wochentage: keine Übergabe.",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "wochentag",
                    "von",
                    "bis"
                  ],
                  "properties": {
                    "wochentag": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 7,
                      "description": "ISO 8601: 1 = Montag bis 7 = Sonntag."
                    },
                    "von": {
                      "type": "string",
                      "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
                      "description": "Beginn, hh:mm in der Zeitzone unter zeitzone."
                    },
                    "bis": {
                      "type": "string",
                      "pattern": "^([01][0-9]|2[0-4]):[0-5][0-9]$",
                      "description": "Ende, hh:mm."
                    }
                  }
                }
              }
            }
          }
        },
        "buchungszeiten": {
          "type": "array",
          "description": "Zeiten, zu denen Termine gebucht werden können, je Wochentag. Fehlende Wochentage: keine Buchung.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "wochentag",
              "von",
              "bis"
            ],
            "properties": {
              "wochentag": {
                "type": "integer",
                "minimum": 1,
                "maximum": 7,
                "description": "ISO 8601: 1 = Montag bis 7 = Sonntag."
              },
              "von": {
                "type": "string",
                "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
                "description": "Beginn, hh:mm in der Zeitzone unter zeitzone."
              },
              "bis": {
                "type": "string",
                "pattern": "^([01][0-9]|2[0-4]):[0-5][0-9]$",
                "description": "Ende, hh:mm."
              }
            }
          }
        },
        "zeitzone": {
          "type": "string",
          "description": "IANA-Zeitzone, z. B. Europe/Berlin."
        },
        "zielsysteme": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Systeme des Kunden, in die der Voice Agent Anfragen, Rückrufwünsche, Termine und Gesprächsnotizen schreibt, z. B. „NexAI CRM“. Nur die Bezeichnung, keine Zugangsdaten."
        },
        "benachrichtigungEmail": {
          "type": "string",
          "description": "Adresse des Kunden für Hinweise zu Rückrufwünschen und Terminen, soweit eingerichtet."
        }
      }
    },
    "anrufe": {
      "type": "array",
      "description": "Anrufdatensätze beim Plattformanbieter, soweit noch gespeichert.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "kennung",
          "beginn",
          "dauerSekunden",
          "richtung",
          "von",
          "an"
        ],
        "properties": {
          "kennung": {
            "type": "string",
            "description": "Kennung des Anrufs beim Plattformanbieter."
          },
          "beginn": {
            "type": "string",
            "format": "date-time",
            "description": "Beginn, nach RFC 3339."
          },
          "ende": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time",
            "description": "Ende, nach RFC 3339."
          },
          "dauerSekunden": {
            "type": "integer",
            "minimum": 0
          },
          "richtung": {
            "enum": [
              "eingehend",
              "ausgehend"
            ]
          },
          "von": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rufnummer des Anrufers nach E.164; null, wenn sie unterdrückt war."
          },
          "an": {
            "type": "string",
            "description": "Angerufene Rufnummer nach E.164."
          },
          "endeGrund": {
            "type": "string",
            "description": "Grund des Gesprächsendes, wie der Plattformanbieter ihn meldet, z. B. aufgelegt oder weitergeleitet."
          },
          "weitergeleitetAn": {
            "type": [
              "string",
              "null"
            ],
            "description": "Weiterleitungsziel, wenn der Anruf übergeben wurde."
          },
          "notiz": {
            "type": [
              "string",
              "null"
            ],
            "description": "Zusammenfassung des Gesprächs, falls der Plattformanbieter sie für diesen Anruf gespeichert hat; sonst null. Die Gesprächsnotiz im Zielsystem wird dort exportiert."
          },
          "protokoll": {
            "type": "array",
            "description": "Gesprächsprotokoll beim Plattformanbieter, solange es dort gespeichert ist (rund 14 Tage); danach leer. Es enthält technische Ereignisse und die dort protokollierten Äußerungen im Gespräch, also die erkannten Sätze des Anrufers und die Antworten des Voice Agents.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "zeitpunkt",
                "ereignis"
              ],
              "properties": {
                "zeitpunkt": {
                  "type": "string",
                  "format": "date-time"
                },
                "ereignis": {
                  "type": "string",
                  "description": "z. B. Äußerung des Anrufers, Antwort des Voice Agents, Werkzeug aufgerufen, Übergabe, Fehler."
                },
                "text": {
                  "type": "string"
                }
              }
            }
          },
          "wortprotokoll": {
            "type": "array",
            "description": "Vollständiges Wortprotokoll, nur wenn der Kunde es beauftragt hat; sonst leer.",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "sprecher",
                "text"
              ],
              "properties": {
                "sprecher": {
                  "enum": [
                    "anrufer",
                    "voiceAgent"
                  ]
                },
                "abSekunde": {
                  "type": "number",
                  "minimum": 0
                },
                "text": {
                  "type": "string"
                }
              }
            }
          },
          "tonaufzeichnung": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": false,
            "required": [
              "datei",
              "medientyp"
            ],
            "description": "Tonaufzeichnung, nur wenn der Kunde sie beauftragt hat; im ursprünglichen Format.",
            "properties": {
              "datei": {
                "type": "string",
                "description": "Pfad im Paket, z. B. ton/<kennung>.wav.",
                "pattern": "^ton/[A-Za-z0-9_-][A-Za-z0-9._-]*$"
              },
              "medientyp": {
                "type": "string",
                "description": "Medientyp nach RFC 2046, z. B. audio/wav."
              }
            }
          }
        }
      }
    },
    "verbindungen": {
      "type": "array",
      "description": "Verbindungsdatensätze der Telefonanlage von NexAI, soweit noch gespeichert.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "beginn",
          "dauerSekunden",
          "gespraechSekunden",
          "von",
          "an",
          "status"
        ],
        "properties": {
          "beginn": {
            "type": "string",
            "format": "date-time",
            "description": "Beginn, nach RFC 3339."
          },
          "dauerSekunden": {
            "type": "integer",
            "minimum": 0,
            "description": "Dauer der Verbindung insgesamt."
          },
          "gespraechSekunden": {
            "type": "integer",
            "minimum": 0,
            "description": "Davon angenommen und gesprochen."
          },
          "von": {
            "type": [
              "string",
              "null"
            ],
            "description": "Rufnummer des Anrufers nach E.164; null, wenn sie unterdrückt war."
          },
          "an": {
            "type": "string",
            "description": "Angerufene Rufnummer nach E.164."
          },
          "weitergeleitetAn": {
            "type": [
              "string",
              "null"
            ],
            "description": "Weiterleitungsziel, wenn der Anruf übergeben wurde."
          },
          "status": {
            "enum": [
              "angenommen",
              "nicht angenommen",
              "besetzt",
              "fehlgeschlagen"
            ]
          }
        }
      }
    },
    "nutzungsnachweise": {
      "type": "array",
      "description": "Einzelverbindungsnachweis des Telefonanschlusses, soweit der Anschluss über NexAI läuft; sonst leer.",
      "items": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "beginn",
          "ziel",
          "dauerSekunden",
          "kostenCent"
        ],
        "properties": {
          "beginn": {
            "type": "string",
            "format": "date-time",
            "description": "Beginn, nach RFC 3339."
          },
          "ziel": {
            "type": "string",
            "description": "Angerufene Rufnummer, wie im Einzelverbindungsnachweis des Telefonieanbieters, gegebenenfalls gekürzt."
          },
          "dauerSekunden": {
            "type": "integer",
            "minimum": 0
          },
          "kostenCent": {
            "type": "integer",
            "minimum": 0,
            "description": "Entgelt in Cent, wie vom Telefonieanbieter berechnet."
          }
        }
      }
    }
  }
}
