-
Allgemein
-
Module
-
Tipps & Tricks
API
API Zugriff
Sticky bietet dir einen JSON API-Zugriff, sodass du auf deine Firma bzw. dein Nutzerprofil zugreifen kannst, um Aufrufe oder Abläufe zu automatisieren.
API Domain
Deine Anfragen richtest du gegen folgende Domain via HTTPS.
- Live Umgebung: https://app.sticky.de
- Sandbox Umgebung: https://dvl.sticky.de
Authentifizierung
Die Authentifizierung an der Sticky-API besteht immer aus drei verschiedenen „Tokens“. Diese drei Tokens werden bei jedem Aufruf als HTTP-Header angegeben. Im Standard ist der API-Zugriff für einen Benutzer deaktiviert. Du kannst in deinem Profil im Menüpunkt „API-Zugriff“ die API für deinen Account aktivieren und findest dort die drei Tokens.
Gebe deinen API-Zugangstoken bitte NIEMALS an andere Personen weiter!
- Sticky-Token
- Dieser Token ist dein persönliches Geheimnis.
- 36-stelliger Token
- Sticky-User
- Dieser Token identifiziert deinen Benutzerkontext
- 24-stelliger Token
- Sticky-Company
- Dieser Token identifiziert deinen Firmenkontext
- 24-stelliger Token
Ein Benutzer mit Zugriff auf mehrere Firmen:
In Sticky ist es natürlich möglich, dass du als Benutzer mit einem einzigen Account Zugriff auf multiple Firmen hast. Aus diesem Grund gibst du in einem API-Aufruf sowohl deinen Benutzerkontext (in welchen Benutzerrechten möchtest du agieren) sowie einen Firmenkontext (in welcher Firma möchtest du agieren) an.
Welche Endpunkte du ansprechen kannst, sind entweder im Hilfetext des jeweiligen Moduls hinterlegt oder wir stimmen das gerne im Detail mit dir ab, sofern nicht bekannt. Öffne dazu bitte einfach ein Support-Ticket.
Parameter
Um dich bei einer einfachen Implementierung zu unterstützen, kannst du die benötigten Parameter entweder als GET (URL-Parameter), POST (Formulardaten) oder als POST (JSON Payload) senden. Dies ist zwar technisch eher ungewöhnlich, jedoch ist so eine Implementierung auf deiner Seite wesentlich einfacher, da wir dir keine festen Vorgaben in Bezug auf HTTP-Methode und Format der Parameter machen. Je nach Umgebung, die du vorfindest, ist die eine oder andere Version zielführender.
Es gibt grundlegend immer folgende Parameter:
m // pflicht, das angesprochene Modul method // pflicht, der angesproche Endpunkt
c // optional, abhängig von Endpunkt msg // optional, abhängig von Endpunkt id // optional, abhängig von Endpunkt
Was genau bedeutet dies nun?
Das heißt, dass du die oben beschrieben Parameter bei einem API-Aufruf auf einer der drei gängigen Arten senden darfst. Wenn wir eine Empfehlung aussprechen sollten, würden wir die „JSON Payload“ Variante bevorzugen.
Verdeutlichen wir es an einem Beispiel des Endpunkt „vouchers / send_voucher„.
Beispiel - GET (URL-Parameter) Bei der GET Variante werden die Parameter als URL-Parameter angehangen URL: https://app.sticky.de/?m=vouchers&method=send_voucher&id=RE0265 Payload: leer Beispiel - POST (Formulardaten) Bei der POST Variante werden die Parameter als Payload mitgesendet URL: https://app.sticky.de/ Payload: m=vouchers&method=send_voucher&id=RE0265 Beispiel - POST (JSON Payload) URL: https://app.sticky.de/ Payload: { "m":"vouchers", "method":"send_voucher", "id":"RE0265" }
Wie du siehst, kannst du 3 verschiedene Varianten nutzen, um die Parameter zu übertragen. Das Ergebnis ist jedoch bei allen dasselbe.
Bitte beachte: API Aufrufe funktionieren nur, wenn du via HTTP-Header authentifiziert bist. Du kannst solche Aufrufe aber auch jederzeit in einer Browsernutzung simulieren und testen. Dafür brauchst du nur den Parameter „&json“ an die URL anzuhängen. Durch diesen Zusatz wirst du nicht mehr anhand deiner HTTP-Header authentifiziert, sondern auf Basis deiner aktuellen Browser Sitzung.
Beispiel: https://app.sticky.de/?m=vouchers&method=send_voucher&id=RE0265&json
Protokollierung
Alle API-Aufrufe (inklusive der jeweils übertragenen Parameter) werden in deinem Firmenprotokoll protokolliert.
Beispielaufrufe
CURL
curl -X POST \ --location "https://app.sticky.de/?m=my_module" \ # Endpoint -H "Content-Type: application/json" \ -H "Sticky-Token: 2a3b301d-73c9-e31b-eab4-xxxxxxxxxxxx" \ # The API-Token from the given User-ID -H "Sticky-User: 5ef5d753a91766xxxxxxxxxx" \ # The Sticky User-ID -H "Sticky-Company: 2f8c1f2bcfa625xxxxxxxxxx" # The Company-ID
PHP
$ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => 'https://app.sticky.de/?m=my_module', CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 10, CURLOPT_CUSTOMREQUEST => 'GET', CURLOPT_HTTPHEADER => [ "content-type: application/json", "Sticky-Token: 2a3b301d-73c9-e31b-eab4-xxxxxxxxxxxx", "Sticky-User: 5ef5d753a91766xxxxxxxxxx", "Sticky-Company: 2f8c1f2bcfa625xxxxxxxxxx", ], ]); $response = curl_exec($ch); curl_close($ch); $response_decoded = json_decode($response); print_r($response_decoded);
JavaScript
"use strict"; let token = '2a3b301d-73c9-e31b-eab4-xxxxxxxxxxxx'; let company = '2f8c1f2bcfa625xxxxxxxxxx'; let user = '5ef5d753a91766xxxxxxxxxx'; let api_request = await fetch('https://app.sticky.de/?m=my_module', { method: 'GET', headers: { "Content-Type": "application/json", "Sticky-Token": token, "Sticky-User": user, "Sticky-Company": company } }); let response = await api_request.json(); console.log(json);
Rückgabewerte
Endpunkte geben ein JSON in folgendem Format zurück:
Beispielhafte OK-Rückgabe { "src":"server", // Bei Antworten ist die Quelle immer "Server" "time":1656960905, // Serverseitiger Timestamp "module":"vouchers", // Das angesprochene Modul "method":"send_voucher", // Die angesprochene Methode "msg":"ok", // Die Rückantwort bzw. Payload auf deine Anfrage "id":"", // Sofern eine neue Ressource erzeugt wurde, wird deren ID zurückgegeben } Beispielhafte Rückgabe mit JSON Daten { "src":"server", "time":1656960905, "module":"articles", "method":"get_all", "msg": { // Die Rückantwort bzw. Payload auf deine Anfrage [ {"id":1234, "title":"Datensatz Titel 1", ...}, {"id":1235, "title":"Datensatz Titel 2", ...}, ] }, "id":"", } Beispielhafte Fehler-Rückgabe { "src":"server", "time":1656960905, "module":"system", "method":"access", "msg":"ERROR_API_INVALID_USER", // Die Rückantwort bzw. Payload auf deine Anfrage "id":"", "error":1 // Existiert nur, sofern es sich um eine Fehler-Antwort handelt }
Endpunkte Scope: Firma – Module
Hier findest du eine Aufstellung aller dokumentierten Endpunkte. Sollte dir etwas fehlen, gib uns einfach kurz bescheid oder sende uns eine E-Mail an support@sticky.de. Sicherlich existiert dein gesuchter Endpunkt bereits, jedoch hat er es bisher noch nicht in die Dokumentation geschafft ;-}
Belege
Rechnung per E-Mail versenden
Rechnungen (PDF-Dateien) werden (mit den in den Moduleinstellungen hinterlegten SMTP-Daten und Standardtexten) per E-Mail an die primäre E-Mail-Adresse des Kunden versendet.
Parameter: m | string | vouchers method | string | send_voucher id | string | [Rechnungsnummer oder Sticky-Beleg-ID] Beispiel Anfrage: { "m":"vouchers", "method":"send_voucher", "id":"RE0265" } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"vouchers", "method":"send_voucher", "msg":"ok", "id":"" }
Mögliche Fehlercodes:
– „Belegnummer darf nicht leer sein“
– „Beleg konnte nicht versendet werden. Beleg wurde nicht gefunden, oder wird noch synchronisiert“
– „<smtp error>“
Kontakte
SEPA Mandat aktualisieren
Das SEPA Mandat eines Kunden wird hinterlegt/aktualisiert.
Parameter: m | string | contacts method | string | set_sepa_debit_data id | string | [ID des Kontaktes] msg | object | Folgende Werte müssen enthalten sein: - source | string (optional) | Modulname der Kontaktquelle und Bezug von "id". | Beispiel: Bei einem lexoffice.de Kontakt wird der Modulname "lexoffice" als "source" verwendet. | Wenn nicht angegeben, oder leer, wird die ID eines Sticky-Kontaktes erwartet. - sepa_name | string | Name des Kontoinhabers - sepa_iban | string | IBAN wird auf Gültigkeit geprüft - sepa_bic | string | Wert kann leer sein, bei einer "IBAN-Only" Nutzung bei deiner Bank - sepa_id | string | Mandatsreferenz (Meist gleich der Kundenummer) - sepa_date | string | Datum Unterschrift Kunde im Format dd.mm.yyy - sepa_last_used | string | Datum letzte Nutzung für SEPA-Lastschrift dd.mm.yyy (leer, wenn noch nie benutzt) - sepa_type | string | "SEPA Basis-Lastschrift", "SEPA Firmen-Lastschrift", "SEPA Mandat deaktiviert" Beispiel Anfrage: { "m":"contacts", "method":"set_sepa_debit_data", "id":"40490b91-9016-45de-ba4a-a506285064a0", "msg": { "source":"lexoffice", "sepa_name":"Baebeca Solutions GmbH", "sepa_iban":"DE02120300000000202051", "sepa_bic":"BYLADEM1001", "sepa_id":"10005", "sepa_date":"10.03.2021", "sepa_last_used":"10.03.2021", "sepa_type":"SEPA Basis-Lastschrift" } } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"contacts", "method":"set_sepa_debit_data", "msg":"ok", "id":"" }
Mögliche Fehlercodes:
- "<field> darf nicht leer sein"
- "<field> hat ein ungültiges Format"
- "<field> muss existieren"
- "Kontakt konnte nicht gefunden werden"
Kundenummer aktualisieren
Die Kundenummer in der angeschlossenen Buchhaltungssoftware wird für einen Kontakt aktualisiert.
Einschränkungen, die beachtet werden müssen:
- Kundenummern müssen zu dem Nummernkreis im jeweiligen externen Buchhaltungstool passen
- Je nach Buchhaltungsmodul müssen gültige Login-Daten in den Moduleinstellungen hinterlegt sein
- Kundenummern können nur für unbebuchte Kontakte (also es darf keine Rechnung für den Kunden existieren) geändert werden
Parameter: m | string | contacts method | string | update_customer_number id | string | [ID des Kontaktes] msg | object | Folgende Werte müssen enthalten sein: - source | string (optional) | Modulname der Kontaktquelle und Bezug von "id". | Beispiel: Bei einem lexoffice.de Kontakt wird der Modulname "lexoffice" als "source" verwendet. | Wenn nicht angegeben, oder leer, wird die ID eines Sticky-Kontaktes erwartet. - customer_number | string | Neue Kundenummer
Beispiel Anfrage: { "m":"contacts", "method":"update_customer_number", "id":"f8559d8b-52d1-4393-a101-f48f72a177a8", "msg": { "source":"lexoffice", "customer_number":"30889" } } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"contacts", "method":"set_sepa_debit_data", "msg":"ok", "id":"" }
Mögliche Fehlercodes:
– „<field> darf nicht leer sein“
– „<field> hat ein ungültiges Format“
– „Kontakt konnte nicht gefunden werden“
– „Account in <module> Modul ist nicht verknüpft“
– „Kundenummer konnte nicht aktualisiert werden. (<module> Login gescheitert)“
– „Kundenummer konnte nicht aktualisiert werden“
– „Modul <module> unterstützt kein update_customer_number“
Datenfeld(er) aktualisieren
Einzelne oder mehrere Datenfelder werden an einem Kontakt aktualisiert.
Es werden alle vordefinierten Felder eines Kontaktes unterstützt. Beispiele:
- Zahlungsbedingung | billing_time | string
- SEPA Lastschrift, Zahlbar / sofort, Zahlbar / 8 Tage, Zahlbar / 14 Tage, Zahlbar / 30 Tage, Vorkasse
- Beleg Postversand | postal_delivery | bool
Darüber hinaus werden auch alle via Datenstrukturen zusätzlich erzeugten Felder unterstützt. Selbst erzeugte Felder haben eine eindeutige ID als Feldname (Beispiel: 62cfbf6559d989666f237d72), welche in der UI am HTML Element ausgelesen werden kann.
Parameter: m | string | contacts method | string | set_fields id | string | [ID des Kontaktes] msg | object | Folgende Werte müssen enthalten sein: - source | string (optional) | Modulname der Kontaktquelle und Bezug von "id". | Beispiel: Bei einem lexoffice.de Kontakt wird der Modulname "lexoffice" als "source" verwendet. | Wenn nicht angegeben, oder leer, wird die ID eines Sticky-Kontaktes erwartet. - fields | array | Array, bestehend aus Objekten der gewünschten Updates - field | string | ID / Name des Feldes - value | depending | Wert Beispiel Anfrage (Zwei Standard Felder): { "m":"contacts", "method":"set_fields", "id":"f8559d8b-52d1-4393-a101-f48f72a177a8", "msg": { "source":"lexoffice", "fields": [ {"field":"billing_time", "value":"Vorkasse"}, {"field":"postal_delivery", "value":true} ] } } Beispiel Anfrage (Ein Custom Feld): { "m":"contacts", "method":"set_fields", "id":"f8559d8b-52d1-4393-a101-f48f72a177a8", "msg": { "source":"lexoffice", "fields": [ {"field":"62cfbf6559d989666f237d72", "value":"Mein eigener Wert"} ] } } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"contacts", "method":"set_fields", "msg":"ok", "id":"" }
Mögliche Fehlercodes:
– „<field> darf nicht leer sein“
– „<field> hat ein ungültiges Format“
– „Kontakt konnte nicht gefunden werden“
– „<field> existiert nicht in Datenstruktur“
– „<field> hat ein falsches Datenformat“
– „<field> unbekannter Feldtyp“
Datenstrukturen
Neuen Datensatz anlegen
Es wird ein neuer Datensatz in einer individuell angelegten Datenstruktur erzeugt.
Aktuelle Einschränkungen:
- Es können keine Multi-Tab-Einträge innerhalb eines Datensatzes erzeugt werden.
- Es werden die folgenden Feldtypen unterstützt: Text- Zahlenfeld, Textbox, Liste, Checkbox, Tags.
Felder in Datenstrukturen haben jeweils eine eindeutige ID als Feldname (Beispiel: 62cfbf6559d989666f237d72), welche in der UI am HTML Element ausgelesen werden kann. Der nötige Parameter „c“ kann aus der URL entnommen werden, wenn man die Datenstruktur im UI öffnet.
Parameter: m | string | custom
c | string | [ID der Datenstruktur] method | string | add_item msg | object |
- title | string | [Anzeigename des Eintrages]
- ... | mixed | Beliebige Werten aus der jeweiligen Datenstruktur
Beispiel Anfrage: { "m":"custom",
"c":"64cf55bda39cd440a9663427", "method":"add_item", "msg": { "title":"Mein Datensatz", // Textfeld "64cf5f2b5ccc66298129ef02":"20.10.2010", // Textfeld (Filter: Datum) "64cf5f5e986bd015d0528662":true, // Checkbox
"64cf5f5e986bd015d0528648":"Erdbeere,Apfel,Banane" // Tags } } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"64cf55bda39cd440a9663427", "method":"add_item", "msg":"ok", "id":"64cf69b8df3743757552ae83" // Die ID des erzeugten Datensatzes }
Mögliche Fehlercodes:
- "id muss leer sein"
- "<field> darf nicht leer sein"
- "<field> existiert nicht in Datenstruktur"
- "<field> hat einen nicht unterstützen Feldtyp <typ>"
Generische Endpunkte pro Modul
Diese Endpunkte stehen für alle Module zur Verfügung.
Konfiguration aktualisieren
Die Moduleinstellungen des jeweiligen Moduls können aktualisiert werden.
Eine Konfiguration in den Moduleinstellungen hat jeweils eine eindeutige ID als Feldname, welche in der UI am HTML Element ausgelesen werden kann.
Parameter: m | string | custom
method | string | set_config msg | object | [id => value]
Beispiel Anfrage: { "m":"vouchers",
"method":"set_config", "msg": { "CFG_AUTOSEND_INVOICE":true, "CFG_SEND_POSTAL_IF_NO_EMAIL":false, } } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"vouchers", "method":"set_config", "msg":"ok", }
Mögliche Fehlercodes:
- "Fehlende Admin Berechtigungen"
- "msg darf nicht leer sein"
- "Unbekannte Konfiguration: <config-id>"
Endpunkte Scope: Firma – Allgemein
Hier findest du eine Aufstellung aller dokumentierten Endpunkte. Sollte dir etwas fehlen, gib uns einfach kurz bescheid oder sende uns eine E-Mail an support@sticky.de. Sicherlich existiert dein gesuchter Endpunkt bereits, jedoch hat er es bisher noch nicht in die Dokumentation geschafft ;-}
Für diesen Scope muss der Benutzer immer über Administrationsrechte verfügen.
Logfiles
Logfiles auslesen
Parameter: m | string | system
method | string | get_logfiles msg | object |
- n | int | default 100 | max 1.000
- start | int | optional timestamp
- end | int | optional timestamp
Beispiel Anfrage: { "m":"system",
"method":"get_logfiles", "msg":{
"n":10,
"start":1692512495 } Beispiel Antwort: { "src":"server", "time":1656968326, "module":"system", "method":"get_logfiles", "msg":[
{
"id":"64e1b0f19950e038b711d8c3",
"pid":"0x3781a6",
"account_id":"5ef5d753a9f173334b767334",
"severity":"notice",
"created":1692512497,
"module":"vouchers",
"message:"Datei RE0001.jpg wird heruntergeladen"
},
{
"id":"64e1b0f146ed520b1f5b4c62",
"pid":"0xe01ec2",
"account_id":"5ef5d753a9f173334b767334",
"severity":"notice",
"created":1692512497,
"module":"vouchers",
"message":"Datei RE0004.jpg wird heruntergeladen"
}
] }
Endpunkte Scope: Benutzer
Hier findest du eine Aufstellung aller dokumentierten Endpunkte. Sollte dir etwas fehlen, gib uns einfach kurz bescheid oder sende uns eine E-Mail an support@sticky.de. Sicherlich existiert dein gesuchter Endpunkt bereits, jedoch hat er es bisher noch nicht in die Dokumentation geschafft ;-}