Dokumentace API

Tlačítko Odeslat přes Peppol

Dejte svým uživatelům možnost odesílat dokumenty přímo přes síť Peppol z vašeho webu — jedním tlačítkem. CDN skript badge-sender.js vykreslí tlačítko „Doručit přes Peppol", jehož kliknutím přesměruje na hostovanou stránku web-sender, kde proběhne celé odeslání.

Potřebujete affiliate token (UUID), který získáte v aplikaci v sekci Nastavení → Affiliate. Token identifikuje vašeho účastníka a umožní zobrazení tlačítka.

Jak to funguje

  1. Na stránce vykreslíte tlačítko s UUID affiliate tokenu, URL dokumentu faktury (dostupné z internetu) a formátem (např. isdoc, pdf, zugferd).
  2. Uživatel klikne na tlačítko — přesměruje se na web-sender na adrese https://app.pepposch.eu/web-sender.
  3. Web-sender ověří affiliate token, případně vyzve uživatele k přihlášení, stáhne a automaticky rozpozná formát dokumentu (ISDOC, ISDOCX, PDF+ISDOC, ZUGFeRD, Factur-X), zkontroluje, zda je příjemce registrován v síti Peppol, a zobrazí potvrzovací dialog.
  4. Uživatel potvrdí a dokument je odeslán přes síť Peppol.

Živý náhled

// What happens when the user clicks the badge:
//
// URL mode:
// 1. Browser opens: https://app.pepposch.eu/web-sender
//    with query params:
//      ?url=https%3A%2F%2Fyour-server.example%2Finvoice.isdoc
//      &format=isdoc
//      &affiliateId=YOUR-AFFILIATE-UUID
//
// Inline / prepareDocument mode:
// 1. Browser opens: https://app.pepposch.eu/web-sender
//    with query params:
//      ?data=<base64url-deflate-raw-encoded-document>
//      &format=isdoc
//      &affiliateId=YOUR-AFFILIATE-UUID
//    (prepareDocument: badge-sender.js calls the callback BEFORE navigating
//     and compresses the returned string with CompressionStream/deflate-raw)
//
// 2. The web-sender page:
//    a. Validates the affiliateId
//    b. Checks if the user is logged in (redirects to login if not)
//    c. Downloads the document from 'url' OR decodes+decompresses 'data'
//    d. Looks up whether the recipient is registered in Peppol
//    e. Matches the document sender to one of the user's participants
//    f. Shows a confirmation card → user clicks "Odeslat přes Peppol"
//    g. Document is imported + sent via the Peppol network

Varianta 1 — HTML atributy data-* (nejjednodušší)

Vložte kontejnerový prvek a přidejte atributy data-* přímo na tag &lt;script&gt;. Skript se automaticky inicializuje po načtení.

<!-- 1. Place a container where the button should appear -->
<div id="peppol-send-btn"></div>

<!-- 2. Load the CDN script with data attributes -->
<script
  src="https://app.pepposch.eu/cdn/badge-sender.js"
  data-target="peppol-send-btn"
  data-affiliate-id="YOUR-AFFILIATE-UUID"
  data-url="https://your-server.example/invoice.isdoc"
></script>

Varianta 2 — JavaScript API

Pro větší kontrolu (např. dynamické URL, více tlačítek) zavolejte pepposhShowSendBadge() přímo.

<!-- 1. Container element -->
<div id="peppol-send-btn"></div>

<!-- 2. Load script (no data- attributes needed) -->
<script src="https://app.pepposch.eu/cdn/badge-sender.js"></script>

<!-- 3. Call the API -->
<script>
  pepposhShowSendBadge({
    targetId:    "peppol-send-btn",
    affiliateId: "YOUR-AFFILIATE-UUID",
    url:         "https://your-server.example/invoice.isdoc",
  });
</script>

Varianta 3 — Inline data (bez veřejné URL)

Pokud vaše dokumenty nejsou veřejně dostupné (např. za autentizací nebo na privátním serveru), můžete obsah dokumentu vložit přímo do URL tlačítka pomocí volby inline / atributu data-inline. Dokument je komprimován metodou deflate-raw a zakódován jako base64url.

Typická ISDOC XML faktura (10–20 KB) se zkomprimuje na 2–5 KB. Vyhněte se inline módu pro dokumenty větší než cca 50 KB.

// Node.js — encode document for inline delivery (no external libraries needed)
// Compression uses Node.js built-in 'zlib'; base64url needs no helper either.
const zlib = require('node:zlib');

/**
 * Compress a document buffer and return a base64url string.
 * Deflate-raw is supported natively by both Node.js and modern browsers.
 */
function encodeInlineDocument(buffer) {
  const compressed = zlib.deflateRawSync(buffer);
  return compressed
    .toString('base64')
    .replace(/\+/g, '-')   // base64url: + → -
    .replace(/\//g, '_')   //             / → _
    .replace(/=/g,  '');   //  strip padding
}

// Usage example:
const fs = require('fs');
const inlineData = encodeInlineDocument(fs.readFileSync('invoice.isdoc'));
// inlineData is now safe to embed directly in a URL or HTML attribute.
<!-- Inline mode: document content is embedded directly — no server URL needed -->
<div id="peppol-send-btn"></div>

<script
  src="https://app.pepposch.eu/cdn/badge-sender.js"
  data-target="peppol-send-btn"
  data-affiliate-id="YOUR-AFFILIATE-UUID"
  data-inline="<!-- YOUR-BASE64URL-ENCODED-DOCUMENT -->"
  data-format="isdoc"
></script>
// Inline mode via JavaScript API
pepposhShowSendBadge({
  targetId:    "peppol-send-btn",
  affiliateId: "YOUR-AFFILIATE-UUID",
  inline:      "<!-- YOUR-BASE64URL-ENCODED-DOCUMENT -->",
  format:      "isdoc",
});

// The 'inline' value is produced server-side:
// zlib.deflateRawSync(buffer).toString('base64')
//   .replace(/\+/g,'-').replace(/\//g,'_').replace(/=/g,'')

Varianta 4 — callback prepareDocument (generování dokumentu při kliknutí)

Použijte prepareDocument, pokud neexistuje předem připravená URL ani inline payload — například když je dokument generován dynamicky v prohlížeči v okamžiku kliknutí. Callback nepřijímá argumenty a musí vrátit obsah dokumentu (např. ISDOC XML) nebo Promise.

Komprese: badge-sender.js vždy zkusí komprimovat vrácený obsah pomocí prohlížečového API CompressionStream (deflate-raw) před sestavením URL. Pokud API není dostupné (starší prohlížeče), použije prosté base64url kódování. Server oba varianty transparentně zpracuje.

Během přípravy dokumentu je tlačítko dočasně deaktivováno (zešedlé), aby se zabránilo vícenásobnému odeslání. Po chybě se automaticky znovu aktivuje.

// Option 4: prepareDocument callback
// Use when neither a public URL nor pre-encoded inline is available
// (e.g. the document is generated on-the-fly in the browser).
pepposhShowSendBadge({
  targetId:       "peppol-send-btn",
  affiliateId:    "YOUR-AFFILIATE-UUID",
  format:         "isdoc",

  // Called when the user clicks the badge.
  // Return the raw document content (ISDOC XML, ZUGFeRD XML, …) as a string.
  // The script compresses it with the browser's CompressionStream API
  // (deflate-raw) and embeds the result in the redirect URL.
  // Falls back to plain base64url if CompressionStream is unavailable.
  prepareDocument: async function () {
    const invoice = await myApp.generateIsdocXml();
    return invoice; // raw XML string — badge-sender.js handles compression
  },
});

// Combine with pepposhUpdateSendBadge to refresh the callback:
pepposhUpdateSendBadge("peppol-send-btn", {
  prepareDocument: async function () {
    return await myApp.generateIsdocXml();
  },
});
// Browser-side compression (badge-sender.js internal — shown for reference)
//
// badge-sender.js always tries to compress inline / prepareDocument content
// using the browser's built-in CompressionStream API before building the URL.
// This keeps the redirect URL as short as possible.
//
// The server (web-sender/preview + import-from-url endpoints) automatically
// detects whether the received 'data' parameter is deflate-raw compressed and
// decompresses it transparently. If decompression fails it treats the payload
// as plain base64url content.
//
// The server-side (Node.js) encoding helper for pre-compressed payloads:
const zlib = require('node:zlib');

function encodeInlineDocument(buffer) {
  return zlib.deflateRawSync(buffer)
    .toString('base64')
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=/g,  '');
}

// Usage:
const encoded = encodeInlineDocument(fs.readFileSync('invoice.isdoc'));
// Pass as:  inline: encoded

Ověření příjemce (volitelné)

Aby bylo možné odeslat fakturu přes síť Peppol, musí být příjemce v síti registrován. Zadání identity příjemce umožní uživateli okamžitou zpětnou vazbu, zda je odeslání možné ještě před kliknutím.

Zadejte DIČ příjemce v EU nebo kód země + IČ. Tlačítko provede klientský Peppol lookup ihned po vykreslení a přepne se na jednu ze tří variant obrázku podle výsledku:

Pouze na straně klienta. Pole euVatId, countryCode a rn jsou využívána výhradně v prohlížeči pro zobrazení obrázku tlačítka — nikdy nejsou zahrnuta do URL otevřené po kliknutí. Web-sender stránka čte příjemce z dokumentu samotného.
<!-- Recipient verification using EU VAT ID -->
<div id="peppol-send-btn"></div>

<script
  src="https://app.pepposch.eu/cdn/badge-sender.js"
  data-target="peppol-send-btn"
  data-affiliate-id="YOUR-AFFILIATE-UUID"
  data-url="https://your-server.example/invoice.isdoc"
  data-eu-vat-id="CZ12345678"
></script>

<!-- Or using country code + registration number -->
<script
  src="https://app.pepposch.eu/cdn/badge-sender.js"
  data-target="peppol-send-btn"
  data-affiliate-id="YOUR-AFFILIATE-UUID"
  data-url="https://your-server.example/invoice.isdoc"
  data-country-code="CZ"
  data-rn="12345678"
></script>
pepposhShowSendBadge({
  targetId:    "peppol-send-btn",
  affiliateId: "YOUR-AFFILIATE-UUID",
  url:         "https://your-server.example/invoice.isdoc",

  // Identify the recipient — provide euVatId OR countryCode + rn.
  // These fields are used CLIENT-SIDE ONLY to drive the badge image.
  // They are never included in the URL opened when the user clicks.
  euVatId:     "CZ12345678",   // EU VAT ID (preferred)
  // -- or --
  countryCode: "CZ",           // ISO 3166-1 alpha-2 country code
  rn:          "12345678",     // Registration / company number

  // Badge will changed design based on registration status:
  //   Checking / error / no info 
  //   Recipient on Peppol        
  //   Recipient NOT on Peppol    
});

Dynamická aktualizace URL

Při vygenerování nové faktury (např. po odeslání formuláře) aktualizujte tlačítko bez znovu-vykreslení celé stránky:

// After generating a new invoice, update the button URL
// without re-rendering the whole badge:
pepposhUpdateSendBadge(
  "peppol-send-btn",
  "https://your-server.example/invoice-20240418.isdoc"
);

// Or pass a full options object to change multiple fields:
pepposhUpdateSendBadge("peppol-send-btn", {
  url:         "https://your-server.example/new-invoice.isdoc",
  affiliateId: "YOUR-AFFILIATE-UUID",
  format:      "isdoc",
});

// In inline mode, update with new encoded data:
pepposhUpdateSendBadge("peppol-send-btn", {
  inline:      newBase64urlEncodedData,
  affiliateId: "YOUR-AFFILIATE-UUID",
  format:      "isdoc",
});

Integrace do React, Vue nebo Angular

Načtěte skript jednou a zavolejte pepposhShowSendBadge po připojení komponenty. Znovu zavolejte při změně URL.

// React / Vue / Angular — render into a ref after mount
import { useEffect, useRef } from "react";

function SendButton({ affiliateId, invoiceUrl }) {
  const ref = useRef(null);

  useEffect(() => {
    if (!invoiceUrl) return;

    const script = document.createElement("script");
    script.src = "https://app.pepposch.eu/cdn/badge-sender.js";
    script.onload = () => {
      window.pepposhShowSendBadge({
        targetId:    "peppol-send-btn",
        affiliateId,
        url:         invoiceUrl,
      });
    };
    if (!document.querySelector('script[src*="badge-sender"]')) {
      document.head.appendChild(script);
    } else {
      window.pepposhShowSendBadge?.({
        targetId: "peppol-send-btn",
        affiliateId,
        url: invoiceUrl,
      });
    }
  }, [affiliateId, invoiceUrl]);

  return <div id="peppol-send-btn" />;
}

API reference

pepposhShowSendBadge(options)

Vykreslí tlačítko pro odeslání uvnitř prvku identifikovaného options.targetId. Stávající tlačítko v daném prvku je nahrazeno.

ParametrTypPovinnýPopis
targetIdstringanoID kontejnerového DOM prvku, do kterého se tlačítko vykreslí.
affiliateIdstring (UUID)anoUUID affiliate tokenu z Nastavení → Affiliate. Slouží primárně jako veřejný API klíč — server jej ověřuje před zpracováním; sekundárně umožňuje affiliate tracking.
urlstringano*Veřejná HTTPS URL dokumentu faktury k odeslání. Tlačítko je deaktivováno, pokud není zadána ani url, ani inline, ani prepareDocument.
inlinestringano*Obsah dokumentu zakódovaný jako base64url (komprimovaný deflate-raw nebo prostý). Použijte místo url, když dokument nemá veřejnou URL. Generuje se na serveru pomocí Node.js vestavěného zlib — bez dalších knihoven. badge-sender.js navíc zkusí payload před sestavením URL dále zkomprimovat v prohlížeči.
prepareDocument() => string | Promise<string>ano*Callback zavolaný při kliknutí na tlačítko. Vrátí surový obsah dokumentu (ISDOC XML apod.). badge-sender.js jej zkomprimuje pomocí CompressionStream API a vloží výsledek do URL. Pokud komprese není dostupná, použije prosté base64url.
formatstringneFormát dokumentu. Povolené hodnoty: „isdoc", „isdocx", „pdf" (PDF+ISDOC), „zugferd", „factur-x". Server formát detekuje automaticky z obsahu souboru; tento parametr slouží jako nápověda pro UI tlačítka. Výchozí: „isdoc".
euVatIdstringneDIČ příjemce v EU (např. „CZ12345678"). Pouze na straně klienta — řídí variantu obrázku tlačítka přes Peppol lookup; nikdy není odesláno na server při kliknutí.
countryCodestringneKód země příjemce (ISO 3166-1 alpha-2, např. „CZ"). Pouze na straně klienta — používá se spolu s rn pro Peppol lookup, pokud není zadáno euVatId.
rnstringneIČ příjemce. Pouze na straně klienta — používá se spolu s countryCode pro Peppol lookup.
widthstring | numberneVolitelná šířka obrázku tlačítka (např. 200 nebo „200px").

pepposhUpdateSendBadge(targetId, urlOrOptions)

Aktualizuje již vykreslené tlačítko bez jeho znovu-vytvoření. Předejte prostý řetězec URL nebo objekt s volbami.

ParametrTypPopis
targetIdstringID kontejnerového prvku, ve kterém je tlačítko vykresleno.
urlOrOptionsstring | objectNový řetězec URL, nebo objekt s volbami (stejná pole jako u pepposhShowSendBadge).

Reference atributů data-*

Při použití HTML atributů přidejte tyto na tag &lt;script&gt;:

AtributJS volbaPopis
data-targettargetIdID cílového kontejnerového prvku.
data-affiliate-idaffiliateIdUUID affiliate tokenu.
data-urlurlURL dokumentu faktury.
data-inlineinlineObsah dokumentu zakódovaný jako base64url (deflate-raw). Použijte místo data-url, pokud není veřejná URL k dispozici.
data-formatformatFormát dokumentu: „isdoc" (výchozí), „isdocx", „pdf", „zugferd", „factur-x".
data-eu-vat-ideuVatIdDIČ příjemce v EU pro Peppol lookup (např. „CZ12345678"). Pouze na straně klienta — není předáno serveru.
data-country-codecountryCodeKód země příjemce (ISO 3166-1 alpha-2). Používá se spolu s data-rn. Pouze na straně klienta.
data-rnrnIČ příjemce. Používá se spolu s data-country-code. Pouze na straně klienta.
data-widthwidthVolitelná šířka obrázku tlačítka.

Podporované formáty dokumentů

Server automaticky detekuje skutečný formát ze staženého obsahu souboru (binární signatura nebo XML jmenný prostor). Parametr format slouží jako nápověda pro UI tlačítka.

hodnota formatTyp souboruPříponaPoznámky
isdocISDOC XML.isdocČeská faktura XML. Výchozí formát.
isdocxISDOCX archive.isdocxZIP archiv s ISDOC XML a volitelnými přílohami.
pdfPDF + ISDOC.pdfPDF dokument s vloženou ISDOC XML jako příloha.
zugferdZUGFeRD.pdfPDF dokument s vloženým CII XML (ZUGFeRD 2.x / EN 16931).
factur-xFactur-X.pdfPDF dokument s vloženým Factur-X CII XML. Identický kontejner jako ZUGFeRD.

Požadavky na URL dokumentu

  • Musí být veřejně dostupná přes HTTPS (HTTP je také přijato, ale nedoporučeno).
  • Nesmí odkazovat na privátní IP (127.*, 10.*, 192.168.* apod.) — takové URL jsou serverem blokovány.
  • Dokument musí obsahovat platná fakturní data, která je uživatelský účet oprávněn odeslat.
  • URL by měla zůstat dostupná po dobu alespoň několika minut od vykreslení tlačítka (server ji stahuje ve chvíli, kdy uživatel potvrdí odeslání).

Poznámky k chování

  • Tlačítko je deaktivováno (zešedlé, neklikatelné), pokud chybí url, inline i prepareDocument, nebo pokud chybí affiliateId.
  • Pokud je nastaven prepareDocument, tlačítko zachytí kliknutí, zavolá callback, zkomprimuje výsledek a teprve pak otevře web-sender stránku v novém tabu. Tlačítko je dočasně deaktivováno po dobu přípravy dokumentu. Pokud callback vyhodí výjimku, tlačítko se znovu aktivuje.
  • Jazyk tlačítka (alt text a obrázek) je detekován automaticky z navigator.language prohlížeče. Podporováno: en, cs, de, sk, pl, hu, fr, es, it, ro, pt, hr, sl, uk, nl, da, sv, no, fi, bg, lt, lv, et, el, ru, be, sr, bs, mk, al, mt, ga, cy, is, lu, ua, vi. Záložní: en.
  • Tlačítko vykresluje prvek &lt;a&gt;, který se otevírá v novém tabu (target="_blank").
  • Jeden sdílený tag &lt;script&gt; může obsluhovat libovolný počet tlačítek na téže stránce.
  • Skript lze bezpečně vložit do &lt;head&gt; nebo na konec &lt;body&gt;; čeká na DOMContentLoaded před automatickou inicializací.
  • Styly jsou injektovány jednou (identifikovány unikátním ID), takže vícenásobné vložení skriptu nezpůsobí duplikaci.