Zugangsdaten für die Netze
Die Zugangsdaten eines Kunden für die Netze speichern und ersetzen.
- In der SandboxSpeicherung
- Noch nicht in der SandboxNetze
In einfachen Worten
Zugangsdaten für ein Netz sind der Schlüssel oder die Autorisierung, mit der wir für einen Kunden bei einem Netz oder einer Behörde eines Landes handeln können, etwa ein Token für das nationale E-Rechnungssystem Polens (KSeF). Der Kunde stellt sie aus oder erteilt die Autorisierung, und sie gelangen über die API in eurinvoice, nie per E-Mail oder Chat. Wir speichern sie verschlüsselt und zeigen sie nie wieder an. Die gehostete Sandbox enthält noch keine, deshalb sendet dort ein Übermittlungsweg nichts.
Mit Zugangsdaten für ein Netz können wir für einen Kunden auf einem Übermittlungsweg handeln: ein KSeF-Token, eine ANAF-Autorisierung, ein Plattformschlüssel. Sie werden über diese API übergeben, nie per E-Mail oder Chat. Die API speichert sie und gibt sie nie zurück. Die Aufrufe brauchen einen Schlüssel mit dem Scope admin, und der Schlüssel eines Kunden speichert Zugangsdaten nur für den eigenen Kunden.
Wie ein Wert gespeichert wird
Ein Wert wird vor dem Speichern verschlüsselt, getrennt von dem Schlüssel aufbewahrt, der ihn schützt, und nie wieder angezeigt. Zugangsdaten werden nur geöffnet, wenn der Service den Übermittlungsweg dieses Kunden aufrufen würde. Jede Nutzung schreibt eine Audit-Zeile ohne Wert.
Für Zugangsdaten, deren expires_on weniger als 30 Tage entfernt ist, wird eine Warnmeldung erfasst. Ein Widerruf löscht den Wert und behält die Datumsangaben.
Felder
| Feld | Bedeutung |
|---|---|
client | Die Kennung des Kunden, dieselbe, die auf einer Rechnung steht: 1 bis 64 Buchstaben, Ziffern, Punkte, Unterstriche oder Bindestriche. Der eigene Schlüssel eines Kunden darf sie weglassen. |
route | DE-XRECHNUNG, PEPPOL, FR-PA, PL-KSEF oder RO-EFACTURA. |
kind | Benennt die Zugangsdaten und bestimmt, wie sie gelesen werden, bis zu 80 Zeichen aus Buchstaben, Ziffern, Punkten, Unterstrichen und Bindestrichen: ksef-token für KSeF und anaf-oauth für ANAF. Für einen Peppol- oder Frankreich-Übermittlungsweg nennen wir Ihnen die Art und die Form des Werts, wenn der Produktivstart beginnt. |
issued_by | Wer sie ausgestellt hat, bis zu 200 Zeichen. |
issued_on | Das Ausstellungsdatum, YYYY-MM-DD. |
expires_on | Optional, YYYY-MM-DD. Setzen Sie es, wenn die Zugangsdaten ablaufen. |
environment | Optional. Es muss die Umgebung des aufgerufenen Service sein; eine Sandbox speichert nur Sandbox-Zugangsdaten. |
legal_entity | Optional, bis zu 64 Zeichen. Die Verkäuferkennung, für die die Zugangsdaten handeln: eine USt-IdNr., NIP, SIREN oder Unternehmenskennung. Zugangsdaten ohne sie gelten für die anderen Rechnungen des Kunden. |
value | Das Geheimnis, bis zu 16.384 Zeichen. Pflichtfeld; wird nie zurückgegeben. |
Der Service prüft, ob ein Wert für seine Art funktionieren kann, zum Beispiel ob ein KSeF-Token JSON mit einem nip und einem token ist. Ein anaf-oauth-Wert ist JSON-Text mit einem cui und entweder einem access_token oder einem refresh_token mit client_id und client_secret der Anwendung. Ein Wert, bei dem das nicht der Fall ist, wird mit 422, credential-unusable beantwortet, und die Antwort sagt, welche Form erwartet wird, ohne den Wert zu zitieren.
Eine Antwort enthält id (cred_ und 24 Hex-Zeichen), die Felder oben außer value, stored (true, solange ein Wert gespeichert ist) und revoked_at nach einem Widerruf.
Ein Kunde kann je Übermittlungsweg, kind, Umgebung und Rechtseinheit einen gültigen Satz Zugangsdaten halten. Der Worker nutzt für Kunde und Übermittlungsweg der Rechnung den ältesten nicht widerrufenen Satz.
Zugangsdaten speichern
POST /credentials nimmt die Felder oben als JSON an und antwortet mit 201. Die Anfrage ist credential-create.json.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/credentials" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @credential-create.jsonimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/credentials"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("credential-create.json")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/credentials', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('credential-create.json'),
});
console.log(response.status);
console.log(await response.text());{
"issued_by": "ANAF",
"environment": "sandbox",
"route": "RO-EFACTURA",
"kind": "anaf-oauth",
"expires_on": "2027-09-01",
"stored": true,
"client": "acme-srl",
"issued_on": "2026-09-01",
"id": "cred_5bebc3172daf651a788e4284"
}Werden dieselben Zugangsdaten erneut gespeichert, solange die ersten gültig sind, lautet die Antwort 409.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/credentials" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @credential-create.jsonimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/credentials"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("credential-create.json")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/credentials', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('credential-create.json'),
});
console.log(response.status);
console.log(await response.text());{
"type": "https://eurinvoice.com/problems/credential-exists",
"title": "This client already has this credential",
"status": 409
}Auflisten und lesen
GET /credentials liefert alle Zugangsdaten, gültige und widerrufene, als {"data": [...]}. GET /credentials/{id} liefert einen Satz und 404 für eine ID, die es nicht gibt.
curl "https://api-sandbox-eu.eurinvoice.com/credentials" \
-H "Authorization: Bearer <your-api-key>"import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/credentials"))
.header("Authorization", "Bearer <your-api-key>")
.GET()
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}const response = await fetch('https://api-sandbox-eu.eurinvoice.com/credentials', {
headers: {
Authorization: 'Bearer <your-api-key>',
},
});
console.log(response.status);
console.log(await response.text());{
"data": [
{
"issued_by": "ANAF",
"environment": "sandbox",
"route": "RO-EFACTURA",
"kind": "anaf-oauth",
"expires_on": "2027-09-01",
"stored": true,
"client": "acme-srl",
"issued_on": "2026-09-01",
"id": "cred_5bebc3172daf651a788e4284"
}
]
}Ersetzen
POST /credentials/{id} nimmt einen neuen value an und optional ein neues expires_on. Kunde, Übermittlungsweg, Art und Ausstellungsdatum bleiben. Nutzen Sie es nach einer Token-Erneuerung. Die Anfrage ist credential-replace.json.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/credentials/cred_5bebc3172daf651a788e4284" \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
--data-binary @credential-replace.jsonimport java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.file.Path;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/credentials/cred_5bebc3172daf651a788e4284"))
.header("Authorization", "Bearer <your-api-key>")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofFile(Path.of("credential-replace.json")))
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}import { readFile } from 'node:fs/promises';
const response = await fetch('https://api-sandbox-eu.eurinvoice.com/credentials/cred_5bebc3172daf651a788e4284', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
'Content-Type': 'application/json',
},
body: await readFile('credential-replace.json'),
});
console.log(response.status);
console.log(await response.text());{
"issued_by": "ANAF",
"environment": "sandbox",
"route": "RO-EFACTURA",
"kind": "anaf-oauth",
"expires_on": "2028-09-01",
"stored": true,
"client": "acme-srl",
"issued_on": "2026-09-01",
"id": "cred_5bebc3172daf651a788e4284"
}Widerrufen
POST /credentials/{id}/revoke löscht den Wert und setzt revoked_at. Eine Wiederholung ändert nichts.
curl -X POST "https://api-sandbox-eu.eurinvoice.com/credentials/cred_5bebc3172daf651a788e4284/revoke" \
-H "Authorization: Bearer <your-api-key>"import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Example {
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder(URI.create("https://api-sandbox-eu.eurinvoice.com/credentials/cred_5bebc3172daf651a788e4284/revoke"))
.header("Authorization", "Bearer <your-api-key>")
.POST(HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
}
}const response = await fetch('https://api-sandbox-eu.eurinvoice.com/credentials/cred_5bebc3172daf651a788e4284/revoke', {
method: 'POST',
headers: {
Authorization: 'Bearer <your-api-key>',
},
});
console.log(response.status);
console.log(await response.text());{
"issued_by": "ANAF",
"environment": "sandbox",
"route": "RO-EFACTURA",
"revoked_at": "2026-10-06T19:49:12.987Z",
"kind": "anaf-oauth",
"expires_on": "2028-09-01",
"stored": false,
"client": "acme-srl",
"issued_on": "2026-09-01",
"id": "cred_5bebc3172daf651a788e4284"
}Warnung
Ein widerrufener Datensatz bleibt für den Prüfpfad bestehen. Er kann nicht ersetzt werden: Das wird mit 409, credential-revoked beantwortet. Speichern Sie die neuen Zugangsdaten stattdessen als neuen Datensatz. Ein widerrufener Satz verhindert nicht mehr, dieselbe Kombination aus Kunde, Übermittlungsweg und Art erneut zu speichern.
Antworten
| Status | Bedeutung |
|---|---|
200 | Die Liste, ein Satz Zugangsdaten, ein Ersetzen oder ein Widerruf. |
201 | Gespeichert. |
400 | Der Body ist kein JSON, ein Pflichtfeld fehlt oder ist zu lang, route ist keiner der fünf Werte, oder ein Datum ist nicht YYYY-MM-DD. |
401 | Kein Schlüssel oder ein unbekannter Schlüssel. |
403 | Dem Schlüssel fehlt der Scope admin, oder er nennt einen anderen Kunden. |
404 | Keine solchen Zugangsdaten. |
409 | Der Kunde hat diese Zugangsdaten bereits (credential-exists), oder die Zugangsdaten wurden widerrufen (credential-revoked). |
413 | Der Body ist größer als 5 MB (payload-too-large). |
422 | Der Wert kann für diese Art nicht funktionieren (credential-unusable). |
429 | Zu viele Anfragen für den Schlüssel. Warten Sie Retry-After Sekunden. |
503 | Der Service hat keinen Hauptschlüssel, um einen Wert zu verschlüsseln (unavailable). |
Was jeder Übermittlungsweg braucht
In der Sandboxaus offiziellen Quellen, geprüft am 2. Okt. 2026| Übermittlungsweg | Der Kunde stellt bereit | Wer sie ausstellt | Laufzeit |
|---|---|---|---|
PL-KSEF | Ein KSeF-Token, das Rechnungen senden (InvoiceWrite) und für Statusabfragen lesen kann (InvoiceRead). Seine Berechtigungen werden bei der Erstellung festgelegt, eine Änderung erfordert also ein neues Token. Die Anmeldung mit einem KSeF-Zertifikat wird noch nicht unterstützt. Wird ein ksef-Zugang gespeichert, der kein ksef-token ist, lautet die Antwort 422, credential-unusable. | Der KSeF-Administrator des Kunden. | Siehe den Hinweis unten. |
RO-EFACTURA | Eine OAuth-Autorisierung für unsere registrierte ANAF-Anwendung. | Jemand mit SPV-Rechten für die CUI des Kunden: der gesetzliche Vertreter oder der Buchhalter. Diese Person meldet sich mit einem qualifizierten Zertifikat im Portal der ANAF an. | Das Access-Token gilt 90 Tage, das Refresh-Token 365 Tage. |
PEPPOL | Die Zustimmung, den Kunden als Peppol-Teilnehmer zu registrieren, und die Identitätsprüfung, die der Access Point verlangt. | Der Kunde unterschreibt die Zustimmung und besteht die Prüfung. Den Schlüssel des Access Points verwalten wir, es gibt also keine Zugangsdaten des Kunden zu speichern. | Der Schlüssel des Access Points gehört uns, und wir rotieren ihn. |
FR-PA | Das eigene Konto des Kunden auf seiner Plateforme Agréée und API-Zugangsdaten für das Unternehmen. | Der Kunde legt sie auf seiner Plattform an oder gewährt uns Zugriff. | Von der Plattform festgelegt. Fragen Sie, welche Art sie ausstellt. |
DE-XRECHNUNG | Für Deutschland selbst nichts. Per E-Mail das sendende Postfach. Über Peppol die Registrierung beim Access Point. | Der Kunde. | Entfällt. |
Tipp
Setzen Sie expires_on anhand der Angaben oben, damit die 30-Tage-Warnmeldung ausgelöst wird, bevor ein Refresh-Token abläuft.
Quellen: OAuth-Verfahren der ANAF (Laufzeiten der Token), KSeF-API-Dokumentation: Token (Berechtigungen werden bei der Erstellung eines Tokens festgelegt).
Warnung
Polen: Die Quellen widersprechen sich bei der Frage, wie lange ein KSeF-Token gültig ist. Das Handbuch des Finanzministeriums (Ausgabe vom 9. Feb. 2026) und die Seite zur Anwendung für Steuerpflichtige (geändert am 31. März 2026) sagen, dass Token bis zum 31. Dez. 2026 zur Authentifizierung genutzt werden können. Die Seite mit Fragen und Antworten des Ministeriums sagt, es habe entschieden, Token in KSeF 2.0 ohne Enddatum beizubehalten (Antwort 39). Ein öffentliches Issue im KSeF-API-Repository des Ministeriums bittet es, den Widerspruch zu klären. Geprüft am 2. Okt. 2026. Bis das geklärt ist, rechnen Sie damit, das Token erneuern zu müssen, falls das Ministerium ein Enddatum festlegt. Die Anmeldung mit einem Zertifikat wird noch nicht unterstützt, ein Token ist also der einzige Zugang. Siehe das Handbuch, die Fragen und Antworten und das Issue.