Dokumentation

Das Handbuch zu Ihrem Board

Eine Seite, drei Spuren: Beginnen Sie hier, geben Sie die zweite an die Person weiter, die die Fälle betreut, und die dritte an die Person, die den Code schreibt.

BEGINNEN SIE HIER

Für alle, die verwalten

Aktivieren Sie den Plan, laden Sie Ihr Team ein, legen Sie Ihr Fall-Präfix fest und behalten Sie die Abrechnung im Griff.

Erste Schritte →
IHRE WEBSITE

Für alle, die die Website pflegen

Drei einbettbare Widgets mit einer Script-Zeile: Kontakt, Fall-Eröffnung und Endkunden-Board.

Widgets →
INTEGRATION

Für alle, die integrieren

REST-API mit eigenen Zugangsschlüsseln, signierte Webhooks und inkrementelle Synchronisation.

API-Referenz →

Was das Board ist

Ein Multi-Marken-Support-Board: Sie betreuen IHRE Kunden, unter IHRER Marke, auf unserer Infrastruktur.

Das Support-Board ist eine einzige Warteschlange von Fällen für Ihren Betrieb: Ihre Kunden eröffnen Fälle über Ihre Website (Widgets), per API oder per E-Mail, und Ihr Team betreut sie in einem eigenen Panel unter dash.elportaldelcliente.com. Jeder Fall geht ein, kommt voran und eskaliert, ohne dass jemand wach sein muss — aber abgeschlossen wird er nur mit einem Namen dahinter.

Ihr Board ist ein isolierter Mandant: Ihre Fälle, Ihre Endkunden und Ihre Agenten vermischen sich mit niemandem sonst. Die Isolation ist Teil des Systemdesigns, keine Einstellung, die man vergessen könnte. Fasst unser Staff einen Ihrer Fälle als Support der letzten Instanz an, wird der Zugriff protokolliert, und Sie können ihn einsehen.

Ihre Kunden brauchen kein Konto bei uns. Sie sprechen mit Ihrer Marke: dem Widget, Ihrer Website und Ihrer E-Mail. Das Konto (und die Kontrolle) haben Sie.

Erste Schritte

Von null auf Betrieb, in fünf Schritten.

  1. Erstellen Sie Ihr Konto unter dash.elportaldelcliente.com.
  2. Aktivieren Sie einen Plan. Bezahlt wird mit dem Guthaben Ihres Kontos (dieselbe Geldbörse für das ganze Ökosystem); fehlt etwas, bietet Ihnen der Bildschirm an, genau den Fehlbetrag aufzuladen.
  3. Laden Sie Ihre Agenten ein im Tab «Agenten»: E-Mail und Rolle (Agent oder Administrator). Sie erhalten einen Zugangslink zum Weitergeben.
  4. Schalten Sie ein Widget ein unter «Widgets und API»: Registrieren Sie die Domain Ihrer Website als autorisierten Origin, kopieren Sie das Script und fügen Sie es in Ihre Website ein.
  5. Integrieren Sie per Code? Stellen Sie im selben Tab Ihren tab_live_-Zugangsschlüssel aus und folgen Sie der API-Referenz auf dieser Seite.
Ihr Fall-Präfix: Unter «Widgets und API» können Sie 4 eigene Buchstaben festlegen (zum Beispiel ACME), und Ihre Fälle werden als ACME-1044 nummeriert. Bereits vergebene Fallnummern werden nicht geändert.

Das Board-Panel

Das Mandanten-Panel unter dash.elportaldelcliente.com, Tab für Tab.

TabFunktion
ÜbersichtStatus Ihres Abonnements, Ablauf, Verlängerung und Auto-Verlängerung. Hier wird auch gekündigt.
AgentenPer E-Mail mit Agenten- oder Administratorrolle einladen; Rollen ändern; Zugang entziehen. Der Inhaber bleibt geschützt.
Widgets und APIFall-Präfix, autorisierte Origins (CORS), die drei Widgets mit ihrem Script und die API-Zugangsschlüssel.
Zugriffe des AnbietersDas Audit: jeder Zugriff unseres Staffs auf Ihre Fälle — wer, was und wann.

Die Agenten, die Sie einladen, sehen und betreuen die Fälle Ihres Boards; Administratoren verwalten zusätzlich das Abonnement, das Team und die Integrationen.

Widgets für Ihre Website

Drei Widgets, je eine Script-Zeile. Ohne Dritt-Iframes, ohne Tracking-Cookies.

Im Tab «Widgets und API» Ihres Panels: Schalten Sie das Widget ein, registrieren Sie die Domain Ihrer Website als autorisierten Origin und kopieren Sie das generierte Script. Der Parameter data-color akzeptiert Ihre Markenfarbe.

<script src="https://api.elportaldelcliente.com/api/tablero/widget/tablero.js"
        data-tenant="su-tablero" data-widget="contacto" data-color="#a177ff"></script>
data-widgetFunktionVoraussetzung
contactoKontaktformular: Name, E-Mail und Nachricht. Erstellt einen Fall auf Ihrem Board.Widget eingeschaltet + autorisierter Origin
abrir-casoFall-Eröffnung mit Betreff: gibt dem Besucher die Fallnummer zurück.Widget eingeschaltet + autorisierter Origin
tableroEndkunden-Board: Der Kunde sieht seine Fälle, eröffnet neue und antwortet direkt auf Ihrer Website.Wie oben + Kunden-Token (siehe unten)

Schutzmechanismen des Widgets

Anonyme Widgets akzeptieren 10 Versuche pro Besucher (IP) alle 10 Minuten und Board. Ist das Widget ausgeschaltet, der Origin nicht autorisiert oder das Abonnement abgelaufen, antwortet das Widget mit 404 widget no disponible — absichtlich ununterscheidbar, um die Konfiguration Ihres Boards nicht preiszugeben.

Das Widget «tablero»: Ihren Kunden identifizieren

Das «tablero»-Widget zeigt jedem Endkunden nur seine eigenen Fälle. Dafür tauscht Ihr Server pro Kunde einen kurzlebigen Token ein: Rufen Sie POST /v1/clientes/:ref/token-widget mit Ihrem API-Zugangsschlüssel auf (server-seitig, niemals aus dem Browser) und übergeben Sie den Token an das Widget.

curl -X POST https://api.elportaldelcliente.com/api/tablero/v1/clientes/cli-842/token-widget \
  -H "Authorization: Bearer $TABLERO_KEY"

HTTP/1.1 201
{"success":true,"data":{"token":"tabw_…","expires_at":"2026-08-18 21:15:00"}}
window.TableroPortal.setToken(token);
Der tabw_-Token lebt 15 Minuten und wird nicht verlängert. Läuft er ab, erhält das Widget 401 token_vencido: Tauschen Sie einen neuen ein. Geben Sie Ihren tab_live_-Schlüssel niemals im Browser preis — genau dafür existiert der kurzlebige Token.

API-Zugangsschlüssel

Ein Bearer-Zugangsschlüssel pro Integration, mit begrenztem Umfang und widerrufbar.

Die Zugangsschlüssel werden in Ihrem Panel ausgestellt («Widgets und API» → «API-Zugangsschlüssel»). Sie haben die Form tab_live_… und werden nur ein einziges Mal angezeigt: Bewahren Sie sie in Ihrem Secrets-Manager auf. Wir speichern nur ihren Hash.

curl -H "Authorization: Bearer tab_live_…" \
  https://api.elportaldelcliente.com/api/tablero/v1/

Beim Ausstellen können Sie die Scopes einschränken. Ein Schlüssel ohne explizite Scopes hat Zugriff auf Ihr gesamtes Board:

ScopeErlaubt
casos.readFälle und ihre Antworten lesen
casos.writeFälle erstellen, antworten und Status/Priorität ändern
clientes.readIhre Endkunden lesen
clientes.writeEndkunden anlegen/deaktivieren und Widget-Tokens ausstellen
departamentos.manageAbteilungen lesen und verwalten (inklusive IMAP-Postfächer)
webhooks.manageWebhooks lesen und verwalten
accesos.readDas Zugriffs-Audit des Anbieters lesen
  • Maximal 5 aktive Zugangsschlüssel pro Board. Widerrufen Sie, was Sie nicht mehr nutzen.
  • Der Schlüssel identifiziert Ihr Board: Senden Sie niemals tenant_id im Body — die API lehnt das mit 400 ab.
  • Bei abgelaufenem Abonnement kann der Schlüssel weiterhin lesen (GET); jede Schreiboperation antwortet mit 402 suscripcion_vencida.
  • Ein widerrufener Schlüssel antwortet sofort auf allen Routen mit 401.
Ausschließlich server-seitig. Der tab_live_-Schlüssel gehört niemals in den Browser, in eine Mobile-App oder in ein Repository. Für den Browser gibt es den kurzlebigen tabw_-Token.

API-Referenz

REST über HTTPS, JSON in beide Richtungen, Antworten in der Form {success, data}.

Konventionen: Request-Bodys gehen als Content-Type: application/json; Datumsangaben sind UTC YYYY-MM-DD HH:MM:SS; paginierte Listen liefern total, page und limit. Was nicht Ihnen gehört, antwortet 404, niemals 403: Die API bestätigt die Existenz fremder Ressourcen nicht.

https://api.elportaldelcliente.com/api/tablero/v1

Root: Identität, Plan und Nutzung

GET / ist der Vertrag, der nicht lügen kann: Er liefert, wer Sie sind, welche Scopes dieser Schlüssel hat, Ihren Plan mit seinen Limits, den Status Ihres Abonnements und Ihren bisherigen Verbrauch.

curl -H "Authorization: Bearer $TABLERO_KEY" \
  https://api.elportaldelcliente.com/api/tablero/v1/

{"success":true,"data":{
  "tenant":{"slug":"su-tablero","nombre":"Su Marca"},
  "scopes_de_esta_credencial":["casos.read","casos.write"],
  "plan":{"id":"tablero-base","nombre":"BASE","limites":{"max_agentes":5,"max_departamentos":5,"max_articulos_kb":100}},
  "suscripcion":{"estado":"active","current_period_end":"2027-08-18"},
  "uso":{"agentes":3,"departamentos":2},
  "recursos":["/casos","/clientes","/departamentos","/accesos","/webhooks"],
  "version":"v1"}}

Endkunden

Ein Endkunde ist ein Kunde von Ihnen (kein Konto unseres Ökosystems). Er wird über external_ref identifiziert: die ID, die dieser Kunde in IHREM System hat.

MethodeRouteScopeFunktion
GET/clientesclientes.readKunden auflisten (bis zu 500, neueste zuerst)
POST/clientesclientes.writePer external_ref anlegen oder aktualisieren (idempotentes Upsert)
GET/clientes/:refclientes.readEinen Kunden über seine external_ref lesen
DELETE/clientes/:refclientes.writeDeaktivieren (löscht nicht: die Fall-Historie bleibt erhalten)
POST/clientes/:ref/token-widgetclientes.writeKurzlebigen Token für das Widget «tablero» ausstellen (15 Min.)
curl -X POST https://api.elportaldelcliente.com/api/tablero/v1/clientes \
  -H "Authorization: Bearer $TABLERO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_ref":"cli-842","email":"[email protected]","name":"Maria Rojas"}'
Sichere Wiederholungen: POST /clientes ist ein Upsert per external_ref — ein wiederholter Aufruf dupliziert keine Kunden. Beim Erstellen von Fällen dagegen erzeugt ein Netzwerk-Retry einen neuen Fall: Wiederholen Sie nur, wenn Sie keine Antwort erhalten haben.

Fälle

Die zentrale Ressource. Ein Fall hat Status, Priorität, optional einen Endkunden und eine Konversation aus Antworten. Interne Notizen der Agenten werden über die API niemals offengelegt.

MethodeRouteScopeFunktion
GET/casoscasos.readAuflisten mit Filtern: Status, Kunde, updated_since, limit (1-100), page
POST/casoscasos.writeEinen Fall erstellen (subject erforderlich; cliente_ref, priority, department_id, body/body_html optional)
GET/casos/:idcasos.readDetail mit der vollständigen Konversation (Antworten geordnet). Akzeptiert die ID oder die Fallnummer (z. B. SOLC-1051) gleichermaßen
POST/casos/:id/respuestascasos.writeAls Ihr Team antworten, oder als der Kunde mit en_nombre_de
PATCH/casos/:idcasos.writestatus und/oder priority ändern

Einen Fall erstellen, verknüpft mit einem Endkunden:

curl -X POST https://api.elportaldelcliente.com/api/tablero/v1/casos \
  -H "Authorization: Bearer $TABLERO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"subject":"No puedo entrar al panel","cliente_ref":"cli-842","priority":"high",
       "body":"Al iniciar sesion la pagina queda en blanco."}'

HTTP/1.1 201
{"success":true,"data":{"id":"…","numero":"SOLC-1051"}}

Auflisten mit Filtern, und inkrementelle Synchronisation mit updated_since (ISO 8601): In diesem Modus ist die Reihenfolge updated_at aufsteigend — gedacht, um Seite für Seite voranzugehen, ohne Änderungen zu verlieren. Speichern Sie das höchste verarbeitete updated_at und verwenden Sie es als Cursor für den nächsten Durchlauf.

curl -H "Authorization: Bearer $TABLERO_KEY" \
  "https://api.elportaldelcliente.com/api/tablero/v1/casos?estado=open&cliente=cli-842&limit=50&page=1"

# inkrementelle Synchronisation (Reihenfolge: updated_at aufsteigend)
curl -H "Authorization: Bearer $TABLERO_KEY" \
  "https://api.elportaldelcliente.com/api/tablero/v1/casos?updated_since=2026-08-18T00:00:00Z&limit=100"
Ein Filter, der nicht filtert, ist schlimmer als ein Fehler: ein estado außerhalb der gültigen Liste (oder jeder nicht erkannte Parameter) antwortet mit 400 und dem Detail — nie wird es stillschweigend ignoriert oder die vollständige Liste ohne Warnung zurückgegeben.

Auf einen Fall antworten. Ohne en_nombre_de zeichnet die Antwort als Ihr Team (author_type: agent); mit en_nombre_de zeichnet sie als dieser Endkunde (author_type: client):

curl -X POST https://api.elportaldelcliente.com/api/tablero/v1/casos/$CASO_ID/respuestas \
  -H "Authorization: Bearer $TABLERO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"body":"Ya lo revisamos: intente de nuevo.","autor_nombre":"Soporte Acme"}'

# ...oder im Namen des Endkunden:
  -d '{"body":"Sigue igual desde mi lado.","en_nombre_de":"cli-842"}'
FeldWerte
statusopen · pending · resolved · closed
prioritylow · medium · high · urgent
author_typeclient · agent
Nachprüfbare Isolation: Jede Fall-Abfrage läuft server-seitig durch den Geltungsbereich Ihres Mandanten. Eine Fall-ID eines anderen Boards antwortet 404 — die API verhält sich, als existierte der Fall nicht, denn für Sie existiert er nicht.

Abteilungen

Interne Warteschlangen Ihres Boards (Vertrieb, Abrechnung, Technik…). Jede kann ein eigenes IMAP-Postfach haben: Das Board fragt es ab und wandelt eingehende E-Mails in Fälle um.

MethodeRouteScopeFunktion
GET/departamentosdepartamentos.manageAbteilungen auflisten (inklusive E-Mail-Konfiguration, ohne das Passwort)
POST/departamentosdepartamentos.manageErstellen (name erforderlich; IMAP-Postfach optional; unterliegt dem Plan-Limit)
PUT/departamentos/:iddepartamentos.manageBeliebiges Feld bearbeiten; ein leeres email_password löscht die Zugangsdaten
DELETE/departamentos/:iddepartamentos.manageArchivieren (bestehende Fälle bleiben unberührt)

Das Postfach spricht immer IMAP (email_protocol: imap); das Passwort wird im Ruhezustand verschlüsselt und nie zurückgegeben. Mit email_polling_enabled: 1 läuft die Abfrage automatisch.

Zugriffs-Audit

Jeder Zugriff unseres Staffs auf Fälle Ihres Boards wird protokolliert. Es ist dasselbe Audit wie im Tab «Zugriffe des Anbieters», per API lesbar:

curl -H "Authorization: Bearer $TABLERO_KEY" \
  https://api.elportaldelcliente.com/api/tablero/v1/accesos

Webhooks

Ihr System erfährt es im selben Moment: Jedes Ereignis geht signiert an Ihre HTTPS-URL.

EreignisWird ausgelöst, wenn
caso.creadoEin Fall entsteht auf Ihrem Board — per API, per Widget oder per eingehender E-Mail
caso.respondidoJemand antwortet: Ihr Team (über das Panel oder die API) oder Ihr Endkunde (Widget, API oder E-Mail)
caso.estado_cambiadoDer Status eines Falls ändert sich (durch Ihr Team, die API oder unser System)

Registrieren Sie mit POST /webhooks, so viel Sie brauchen: eine https-URL, die gewünschten Ereignisse und ein Secret von mindestens 16 Zeichen, mit dem wir jede Zustellung signieren.

curl -X POST https://api.elportaldelcliente.com/api/tablero/v1/webhooks \
  -H "Authorization: Bearer $TABLERO_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://su-sistema.com/hooks/tablero",
       "eventos":["caso.creado","caso.respondido","caso.estado_cambiado"],
       "secret":"un-secreto-de-al-menos-16-caracteres"}'

Jede Zustellung ist ein POST mit dem Ereignis, dem Zeitpunkt der Emission und den minimalen Daten zum Reagieren. Die Signatur deckt timestamp.cuerpo ab:

POST /hooks/tablero
Content-Type: application/json
X-Tablero-Evento: caso.respondido
X-Tablero-Timestamp: 1765432100
X-Tablero-Firma: 3f1a…  # HMAC-SHA256(secret, timestamp + "." + cuerpo)

{"evento":"caso.respondido","emitido_at":"2026-08-18T20:15:00.000Z",
 "data":{"caso_id":"…","numero":"SOLC-1051","respuesta_id":"…","autor_tipo":"agent"}}

Die Signatur prüfen

Weisen Sie jede Zustellung zurück, deren Signatur nicht verifiziert oder deren Timestamp mehr als 5 Minuten von der Uhr abweicht. Vergleichen Sie in konstanter Zeit.

// Node.js
const crypto = require('node:crypto');

function verificarFirma(rawBody, headers, secret) {
  const ts  = headers['x-tablero-timestamp'];
  const sig = headers['x-tablero-firma'];
  if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const esperado = crypto.createHmac('sha256', secret)
    .update(ts + '.' + rawBody).digest('hex');
  return sig.length === esperado.length &&
    crypto.timingSafeEqual(Buffer.from(esperado), Buffer.from(sig));
}
# Python
import hashlib, hmac, time

def verificar_firma(raw_body: bytes, headers: dict, secret: str) -> bool:
    ts  = headers.get("x-tablero-timestamp", "")
    sig = headers.get("x-tablero-firma", "")
    if abs(time.time() - float(ts or 0)) > 300:
        return False
    esperado = hmac.new(secret.encode(), f"{ts}.".encode() + raw_body,
                        hashlib.sha256).hexdigest()
    return hmac.compare_digest(esperado, sig)

Zustellsemantik (lesen Sie das, bevor Sie sich darauf verlassen)

  • Ein Versuch pro Ereignis, ohne Wiederholungen. Antwortet Ihr Endpoint nicht innerhalb von 10 Sekunden mit 2xx, ist diese Zustellung verloren — der reale Zustand ist über die API jederzeit erneut lesbar.
  • Ihre Absicherung ist die inkrementelle Synchronisation: Ein periodischer Durchlauf von GET /casos?updated_since=… holt jedes verlorene Ereignis nach.
  • GET /webhooks zeigt fail_count, last_ok_at und last_error_at jedes Webhooks: Prüfen Sie sie beim Debuggen.
  • Die Ereignisse werden unabhängig vom Weg ausgelöst: API, Widgets, das Panel Ihres Teams, unser Staff oder die eingehende E-Mail Ihres Endkunden.

Fehler

JSON-Fehler mit success:false; der HTTP-Code ist maßgeblich.

{"success":false,"error":"…"}
HTTPBedeutung
400Ungültige Anfrage: Ein Pflichtfeld fehlt oder ein Wert besteht die Validierung nicht
401Zugangsschlüssel fehlt, ist ungültig oder widerrufen
402Abonnement abgelaufen: nur Lesen bis zur Verlängerung (suscripcion_vencida)
403Der Schlüssel hat nicht den Scope, den der Endpoint verlangt
404Existiert nicht für Sie: Fremde Ressourcen und nicht vorhandene Routen antworten identisch
409Konflikt: Plan-Limit erreicht oder Slug bereits vergeben
429Zu viele Versuche (anonyme Widgets: 10 pro IP alle 10 Minuten)
500Unser Fehler; falls er anhält, schreiben Sie uns mit der genauen Uhrzeit

Die error-Meldungen sind menschenlesbarer Text und können sich ändern. Verzweigen Sie Ihren Code nach dem HTTP-Code und nach diesen stabilen Slugs:

Stabiler SlugBedeutung
suscripcion_vencida402 bei Schreiboperationen mit abgelaufenem Abonnement
token_vencido401 des Widgets «tablero», wenn der tabw_-Token abgelaufen ist: Tauschen Sie einen neuen ein
saldo_insuficiente402 des Panels beim Aktivieren/Verlängern ohne ausreichendes Guthaben

Pläne

Fünf Jahrespläne, dasselbe Board. Der Unterschied ist, wie viele Menschen und wie viel Struktur hineinpassen.

Die aktuellen Preise werden auf der Startseite und über die öffentliche API (GET /api/public/tablero/plans) veröffentlicht. Alle Pläne enthalten unbegrenzte Fälle, Widgets, API, Webhooks und das Zugriffs-Audit.

PlanAgentenAbteilungenKB-Artikel
ZERO2225
BASE55100
PLUS1010250
PRO2015500
MAX50251000
Ohne kostenlose Testphase, mit Absicht. Der Plan ZERO existiert, um klein anzufangen — mit echtem Commitment. Die Aktivierung bucht das komplette Jahr vom Guthaben Ihres Kontos ab.

Nach Ablauf Ihres Abonnements gibt es eine Karenzzeit; danach wechselt das Board in den Nur-Lese-Modus (GETs antworten weiter, Schreiboperationen liefern 402). Ihre Daten werden nicht gelöscht.

Betriebslimits

  • Fälle: unbegrenzt in allen Plänen. Listen akzeptieren ein limit von 1 bis 100 pro Seite.
  • Endkunden und Audit: Listen liefern bis zu 500 Zeilen (neueste zuerst). Nutzen Sie GET /clientes/:ref für punktuelle Lesezugriffe.
  • Zugangsschlüssel: bis zu 5 aktive pro Board.
  • Anonyme Widgets: 10 Versuche pro Besucher (IP) alle 10 Minuten.
  • Anhänge: Die API akzeptiert noch keine Dateien; Anhänge eingehender E-Mails werden beim Fall aufbewahrt.

Die Trunk-API erzwingt heute keine starre Aufrufquote; arbeiten Sie in einem vernünftigen Rhythmus (Pausen zwischen den Seiten, Wiederholungen mit exponentiellem Backoff). Braucht eine Integration garantiertes Volumen, sprechen Sie vorher mit uns.