[{"data":1,"prerenderedAt":4661},["ShallowReactive",2],{"blog-rest-api-json-einstieg":3,"blog-author-rest-api-json-einstieg":4115,"blog-others-rest-api-json-einstieg":4130,"site-banner":4176,"header-newest-blog":4192,"webinars-next":4202,"crafts-grid-simple-all":4320,"header-success-stories":4410,"feature-topics":4433,"header-schnittstellen":4639},{"id":4,"title":5,"author":6,"body":7,"category":4083,"cta":4084,"description":4087,"draft":4088,"extension":4089,"headline":4090,"icon":4091,"image":4092,"imageAlt":4093,"meta":4094,"navigation":2306,"path":4095,"publishDate":4096,"robots":4097,"seo":4098,"shortDescription":4101,"shortTitle":4102,"showHeaderImage":2306,"showWidgetNewsletter":4088,"slug":4103,"social":4104,"stem":4108,"summary":4109,"tags":4110,"updatedAt":4113,"__hash__":4114},"blog\u002Fblog\u002F260902-rest-api-json-einstieg.md","260902 Rest Api Json Einstieg","frederik",{"type":8,"value":9,"toc":4066},"minimark",[10,14,22,25,94,99,102,105,130,147,157,161,164,230,233,285,303,307,319,322,840,853,856,863,866,951,962,1007,1027,1031,1034,1140,1150,1154,1161,1164,1177,1183,1190,1233,1237,1253,1312,1321,1421,1432,1472,1475,1478,1512,1519,1537,1541,1550,1807,1829,1838,1849,1864,1876,1889,1893,1896,1972,1981,2059,2067,2071,2074,2093,2096,2099,2112,2116,2119,2159,2173,2180,2183,2187,2194,2197,2200,2207,2211,2228,2491,2497,2672,2675,2736,2747,2751,2754,3196,3204,3297,3308,3312,3315,3838,3854,3858,3932,3935,3937,4062],[11,12,13],"p",{},"Du programmierst, aber HTTP und JSON sind dir bisher aus dem Weg gegangen? Du betreust ein konventionelles ERP, eine gewachsene Access-Anwendung oder ein paar VBA-Makros, die seit Jahren ihren Dienst tun? Importe, Exporte und Berichte hast du oft genug gebaut, CSV ist für dich Routine? Und jetzt soll dieses System Daten mit einer Cloud-Anwendung austauschen?",[11,15,16,17,21],{},"Dann bist du hier richtig. Es geht um die Grundlagen einer ",[18,19,20],"strong",{},"REST API",": wie ein Aufruf aufgebaut ist, wie JSON gelesen wird, wo der Schlüssel hingehört und wie der erste Request aus VBA, C# oder Java aussieht.",[11,23,24],{},"Der Umstieg ist überschaubar. Es gibt vier Bausteine, ein Datenformat und eine Handvoll Regeln, und die gelten für jede weitere Schnittstelle genauso, nicht nur für die einer Handwerkersoftware.",[26,27,30],"callout-block",{"title":28,"type":29},"Das Wichtigste in Kürze","tip",[31,32,33,41,61,67,74,77],"ul",{},[34,35,36,37,40],"li",{},"Ein Request besteht aus ",[18,38,39],{},"Methode, URL, Header und Body",". Mehr ist es nicht.",[34,42,43,44,48,49,52,53,56,57,60],{},"Die URL benennt die Ressource, die Methode sagt, was mit ihr passieren soll: ",[45,46,47],"code",{},"GET"," lesen, ",[45,50,51],{},"POST"," anlegen, ",[45,54,55],{},"PATCH"," ändern, ",[45,58,59],{},"DELETE"," löschen.",[34,62,63,66],{},[18,64,65],{},"JSON"," ist verschachtelt und typisiert. Genau darin unterscheidet es sich von einer Zeile CSV.",[34,68,69,70,73],{},"Der Schlüssel gehört in den ",[45,71,72],{},"Authorization","-Header, nie in die URL und nie in den Quellcode.",[34,75,76],{},"Listen kommen seitenweise, bei Artesa mit maximal 20 Datensätzen pro Aufruf. Wer mehr braucht, blättert.",[34,78,79,80,87,88,93],{},"Den ersten Aufruf machst du in ",[81,82,86],"a",{"href":83,"rel":84},"https:\u002F\u002Fwww.postman.com\u002F",[85],"nofollow","Postman"," und nicht im eigenen Code, und einen abgelehnten Body prüfst du mit ",[81,89,92],{"href":90,"rel":91},"https:\u002F\u002Fjsonlint.com\u002F",[85],"JSONLint",".",[95,96,98],"h2",{"id":97},"rest-api-statt-csv-schnittstelle-was-die-cloud-geändert-hat","REST API statt CSV-Schnittstelle: was die Cloud geändert hat",[11,100,101],{},"Im eigenen Haus war eine Schnittstelle eine Frage des Netzwerks. Zwei Programme standen im selben Gebäude, hinter derselben Firewall, und damit gab es zwei naheliegende Wege: eine CSV auf ein Netzlaufwerk legen und vom anderen Programm einlesen, oder gleich per ODBC auf die Datenbank des ERP zugreifen und die Tabellen in Access verknüpfen. Beides funktionierte, weil beide Seiten auf denselben Server sehen konnten.",[11,103,104],{},"Sobald ein System in der Cloud läuft, und jede moderne Handwerkersoftware läuft dort, fällt genau diese Voraussetzung weg. Es gibt kein gemeinsames Laufwerk, und die Datenbank steht in einem Rechenzentrum, auf das dein Programm keinen Netzzugang hat und auch nicht bekommen soll. Was bleibt, ist der einzige Weg, der über das Internet zuverlässig offen ist: HTTP. Und was dort an Daten durchgeht, ist JSON.",[106,107,112,122],"section-container",{":margin-y":108,":padding-x":109,"columns":110,"max-width":111},"true","false","2","none",[113,114,118],"colored-card",{"icon":115,"title":116,"type":117},"tabler:server","Im eigenen Haus","primary",[119,120],"check-list",{":items":121},"[\"CSV auf ein Netzlaufwerk, der andere liest sie ein\",\"ODBC direkt auf die ERP-Datenbank\",\"Verknüpfte Tabellen in Access\",\"Funktioniert, weil beide Seiten im selben Netz stehen\"]",[113,123,127],{"icon":124,"title":125,"type":126},"tabler:cloud","In der Cloud","secondary",[119,128],{":items":129},"[\"Kein gemeinsames Laufwerk, keine erreichbare Datenbank\",\"Ein Request pro Vorgang, Antwort sofort\",\"Rechte hängen am Schlüssel, nicht am Windows-Benutzer\",\"Derselbe Weg für jedes weitere System\"]",[11,131,132,133,137,138,142,143,93],{},"Und der Teil, der den Aufwand rechtfertigt: Das ist keine Artesa-Eigenheit. Buchhaltung, Shop, Auswertung, Verbindungsdienste wie ",[81,134,136],{"href":135},"\u002Fschnittstellen\u002Fn8n","n8n",", alles spricht dieselben zwei Dinge. Wer HTTP und JSON einmal gebaut hat, baut die nächste Anbindung in einem Bruchteil der Zeit, egal gegen welchen Anbieter. Was der Wechsel in die Cloud sonst noch am Betrieb ändert, steht im Blog ",[81,139,141],{"href":140},"\u002Fblog\u002Fcloud-oder-on-premise","„Cloud oder On-Premise\"",", und welche Arten von Schnittstellen es daneben gibt, in ",[81,144,146],{"href":145},"\u002Fblog\u002Fsoftware-schnittstellen","„Software-Schnittstellen\"",[11,148,149,152,153,156],{},[18,150,151],{},"Die URL benennt das Ding, die Methode sagt, was damit passieren soll."," ",[45,154,155],{},"\u002Fv1\u002Fcustomers"," sind die Kunden, und ob du sie lesen, anlegen oder ändern willst, entscheidet nicht die URL, sondern das Verb davor. Genau diese Aufteilung ist alles, was das Wort REST an dieser Stelle bedeutet.",[95,158,160],{"id":159},"aufbau-eines-http-requests-methode-url-header-und-body","Aufbau eines HTTP-Requests: Methode, URL, Header und Body",[11,162,163],{},"Ein Aufruf gegen die Artesa-API sieht ausgeschrieben so aus:",[165,166,171],"pre",{"className":167,"code":168,"language":169,"meta":170,"style":170},"language-http shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","GET \u002Fv1\u002Fcustomers?size=20 HTTP\u002F1.1\nHost: api.artesa.de\nAuthorization: Bearer dein-api-schluessel\nAccept: application\u002Fjson\n","http","",[45,172,173,195,209,219],{"__ignoreMap":170},[174,175,178,181,185,189,192],"span",{"class":176,"line":177},"line",1,[174,179,47],{"class":180},"s7zQu",[174,182,184],{"class":183},"sTEyZ"," \u002Fv1\u002Fcustomers?size=20 ",[174,186,188],{"class":187},"sbssI","HTTP",[174,190,191],{"class":183},"\u002F",[174,193,194],{"class":187},"1.1\n",[174,196,198,202,205],{"class":176,"line":197},2,[174,199,201],{"class":200},"swJcz","Host",[174,203,204],{"class":187},":",[174,206,208],{"class":207},"sfazB"," api.artesa.de\n",[174,210,212,214,216],{"class":176,"line":211},3,[174,213,72],{"class":200},[174,215,204],{"class":187},[174,217,218],{"class":207}," Bearer dein-api-schluessel\n",[174,220,222,225,227],{"class":176,"line":221},4,[174,223,224],{"class":200},"Accept",[174,226,204],{"class":187},[174,228,229],{"class":207}," application\u002Fjson\n",[11,231,232],{},"Vier Bausteine, und jeder hat genau eine Aufgabe:",[31,234,235,244,253,268],{},[34,236,237,240,241,243],{},[18,238,239],{},"Methode",", hier ",[45,242,47],{},": was passieren soll.",[34,245,246,152,249,252],{},[18,247,248],{},"URL",[45,250,251],{},"\u002Fv1\u002Fcustomers?size=20",": womit. Der Pfad benennt die Ressource, alles hinter dem Fragezeichen sind Parameter, die die Anfrage einschränken.",[34,254,255,258,259,261,262,264,265,93],{},[18,256,257],{},"Header",": die Angaben zum Request selbst. Wer fragt, steht in ",[45,260,72],{},", welches Format zurückkommen soll in ",[45,263,224],{},", in welchem Format ein Body geschickt wird in ",[45,266,267],{},"Content-Type",[34,269,270,273,274,276,277,279,280,276,282,284],{},[18,271,272],{},"Body",": die Daten. Bei ",[45,275,47],{}," und ",[45,278,59],{}," bleibt er leer, bei ",[45,281,51],{},[45,283,55],{}," steht dort das JSON.",[11,286,287,288,291,292,297,298,93],{},"Zurück kommen zwei Dinge: ein ",[18,289,290],{},"Statuscode"," und ein Body. Der Statuscode ist die Kurzfassung („hat geklappt\", „darfst du nicht\", „gibt es nicht\"), der Body enthält die Daten oder die Fehlermeldung. Nachschlagen kannst du beides bei MDN, die ",[81,293,296],{"href":294,"rel":295},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fde\u002Fdocs\u002FWeb\u002FHTTP\u002FReference\u002FMethods",[85],"HTTP-Methoden"," und die ",[81,299,302],{"href":300,"rel":301},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fde\u002Fdocs\u002FWeb\u002FHTTP\u002FReference\u002FStatus",[85],"Statuscodes",[95,304,306],{"id":305},"json-verstehen-aufbau-datentypen-und-typische-fehler","JSON verstehen: Aufbau, Datentypen und typische Fehler",[11,308,309,310,191,312,314,315,318],{},"JSON kennt genau zwei Behälter und vier einfache Werte. Objekte stehen in geschweiften Klammern und bestehen aus Schlüssel-Wert-Paaren, Listen stehen in eckigen Klammern. Als Wert erlaubt sind Text in doppelten Anführungszeichen, Zahl, ",[45,311,108],{},[45,313,109],{},", ",[45,316,317],{},"null",", und wieder ein Objekt oder eine Liste. Das ist der ganze Sprachumfang.",[11,320,321],{},"So antwortet die Kundenliste:",[165,323,327],{"className":324,"code":325,"language":326,"meta":170,"style":170},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\n  \"page\": 0,\n  \"pages\": 12,\n  \"size\": 20,\n  \"items\": [\n    {\n      \"id\": 4711,\n      \"number\": \"K-1042\",\n      \"companyName\": \"Metallbau Sander GmbH\",\n      \"externalId\": \"ACC-90231\",\n      \"firstName\": \"Jens\",\n      \"surname\": \"Sander\",\n      \"telephones\": [\n        { \"label\": \"main\", \"isDefault\": true, \"telephoneNumber\": \"+49 381 1234560\" }\n      ],\n      \"emails\": [\n        { \"label\": \"main\", \"isDefault\": true, \"emailAddress\": \"info@metallbau-sander.de\" }\n      ],\n      \"billingAddress\": {\n        \"street\": \"Werftstraße 12\",\n        \"zip\": \"18057\",\n        \"city\": \"Rostock\",\n        \"country\": \"DE\"\n      },\n      \"createdAt\": \"2026-03-14T09:12:04.000Z\",\n      \"updatedAt\": \"2026-08-27T16:40:11.000Z\"\n    }\n  ]\n}\n","json",[45,328,329,335,355,371,387,402,408,427,449,470,491,512,533,547,603,609,623,672,677,692,714,735,756,776,782,803,822,828,834],{"__ignoreMap":170},[174,330,331],{"class":176,"line":177},[174,332,334],{"class":333},"sMK4o","{\n",[174,336,337,340,344,347,349,352],{"class":176,"line":197},[174,338,339],{"class":333},"  \"",[174,341,343],{"class":342},"spNyl","page",[174,345,346],{"class":333},"\"",[174,348,204],{"class":333},[174,350,351],{"class":187}," 0",[174,353,354],{"class":333},",\n",[174,356,357,359,362,364,366,369],{"class":176,"line":211},[174,358,339],{"class":333},[174,360,361],{"class":342},"pages",[174,363,346],{"class":333},[174,365,204],{"class":333},[174,367,368],{"class":187}," 12",[174,370,354],{"class":333},[174,372,373,375,378,380,382,385],{"class":176,"line":221},[174,374,339],{"class":333},[174,376,377],{"class":342},"size",[174,379,346],{"class":333},[174,381,204],{"class":333},[174,383,384],{"class":187}," 20",[174,386,354],{"class":333},[174,388,390,392,395,397,399],{"class":176,"line":389},5,[174,391,339],{"class":333},[174,393,394],{"class":342},"items",[174,396,346],{"class":333},[174,398,204],{"class":333},[174,400,401],{"class":333}," [\n",[174,403,405],{"class":176,"line":404},6,[174,406,407],{"class":333},"    {\n",[174,409,411,414,418,420,422,425],{"class":176,"line":410},7,[174,412,413],{"class":333},"      \"",[174,415,417],{"class":416},"sBMFI","id",[174,419,346],{"class":333},[174,421,204],{"class":333},[174,423,424],{"class":187}," 4711",[174,426,354],{"class":333},[174,428,430,432,435,437,439,442,445,447],{"class":176,"line":429},8,[174,431,413],{"class":333},[174,433,434],{"class":416},"number",[174,436,346],{"class":333},[174,438,204],{"class":333},[174,440,441],{"class":333}," \"",[174,443,444],{"class":207},"K-1042",[174,446,346],{"class":333},[174,448,354],{"class":333},[174,450,452,454,457,459,461,463,466,468],{"class":176,"line":451},9,[174,453,413],{"class":333},[174,455,456],{"class":416},"companyName",[174,458,346],{"class":333},[174,460,204],{"class":333},[174,462,441],{"class":333},[174,464,465],{"class":207},"Metallbau Sander GmbH",[174,467,346],{"class":333},[174,469,354],{"class":333},[174,471,473,475,478,480,482,484,487,489],{"class":176,"line":472},10,[174,474,413],{"class":333},[174,476,477],{"class":416},"externalId",[174,479,346],{"class":333},[174,481,204],{"class":333},[174,483,441],{"class":333},[174,485,486],{"class":207},"ACC-90231",[174,488,346],{"class":333},[174,490,354],{"class":333},[174,492,494,496,499,501,503,505,508,510],{"class":176,"line":493},11,[174,495,413],{"class":333},[174,497,498],{"class":416},"firstName",[174,500,346],{"class":333},[174,502,204],{"class":333},[174,504,441],{"class":333},[174,506,507],{"class":207},"Jens",[174,509,346],{"class":333},[174,511,354],{"class":333},[174,513,515,517,520,522,524,526,529,531],{"class":176,"line":514},12,[174,516,413],{"class":333},[174,518,519],{"class":416},"surname",[174,521,346],{"class":333},[174,523,204],{"class":333},[174,525,441],{"class":333},[174,527,528],{"class":207},"Sander",[174,530,346],{"class":333},[174,532,354],{"class":333},[174,534,536,538,541,543,545],{"class":176,"line":535},13,[174,537,413],{"class":333},[174,539,540],{"class":416},"telephones",[174,542,346],{"class":333},[174,544,204],{"class":333},[174,546,401],{"class":333},[174,548,550,553,555,558,560,562,564,567,569,572,574,577,579,581,584,586,589,591,593,595,598,600],{"class":176,"line":549},14,[174,551,552],{"class":333},"        {",[174,554,441],{"class":333},[174,556,557],{"class":187},"label",[174,559,346],{"class":333},[174,561,204],{"class":333},[174,563,441],{"class":333},[174,565,566],{"class":207},"main",[174,568,346],{"class":333},[174,570,571],{"class":333},",",[174,573,441],{"class":333},[174,575,576],{"class":187},"isDefault",[174,578,346],{"class":333},[174,580,204],{"class":333},[174,582,583],{"class":333}," true,",[174,585,441],{"class":333},[174,587,588],{"class":187},"telephoneNumber",[174,590,346],{"class":333},[174,592,204],{"class":333},[174,594,441],{"class":333},[174,596,597],{"class":207},"+49 381 1234560",[174,599,346],{"class":333},[174,601,602],{"class":333}," }\n",[174,604,606],{"class":176,"line":605},15,[174,607,608],{"class":333},"      ],\n",[174,610,612,614,617,619,621],{"class":176,"line":611},16,[174,613,413],{"class":333},[174,615,616],{"class":416},"emails",[174,618,346],{"class":333},[174,620,204],{"class":333},[174,622,401],{"class":333},[174,624,626,628,630,632,634,636,638,640,642,644,646,648,650,652,654,656,659,661,663,665,668,670],{"class":176,"line":625},17,[174,627,552],{"class":333},[174,629,441],{"class":333},[174,631,557],{"class":187},[174,633,346],{"class":333},[174,635,204],{"class":333},[174,637,441],{"class":333},[174,639,566],{"class":207},[174,641,346],{"class":333},[174,643,571],{"class":333},[174,645,441],{"class":333},[174,647,576],{"class":187},[174,649,346],{"class":333},[174,651,204],{"class":333},[174,653,583],{"class":333},[174,655,441],{"class":333},[174,657,658],{"class":187},"emailAddress",[174,660,346],{"class":333},[174,662,204],{"class":333},[174,664,441],{"class":333},[174,666,667],{"class":207},"info@metallbau-sander.de",[174,669,346],{"class":333},[174,671,602],{"class":333},[174,673,675],{"class":176,"line":674},18,[174,676,608],{"class":333},[174,678,680,682,685,687,689],{"class":176,"line":679},19,[174,681,413],{"class":333},[174,683,684],{"class":416},"billingAddress",[174,686,346],{"class":333},[174,688,204],{"class":333},[174,690,691],{"class":333}," {\n",[174,693,695,698,701,703,705,707,710,712],{"class":176,"line":694},20,[174,696,697],{"class":333},"        \"",[174,699,700],{"class":187},"street",[174,702,346],{"class":333},[174,704,204],{"class":333},[174,706,441],{"class":333},[174,708,709],{"class":207},"Werftstraße 12",[174,711,346],{"class":333},[174,713,354],{"class":333},[174,715,717,719,722,724,726,728,731,733],{"class":176,"line":716},21,[174,718,697],{"class":333},[174,720,721],{"class":187},"zip",[174,723,346],{"class":333},[174,725,204],{"class":333},[174,727,441],{"class":333},[174,729,730],{"class":207},"18057",[174,732,346],{"class":333},[174,734,354],{"class":333},[174,736,738,740,743,745,747,749,752,754],{"class":176,"line":737},22,[174,739,697],{"class":333},[174,741,742],{"class":187},"city",[174,744,346],{"class":333},[174,746,204],{"class":333},[174,748,441],{"class":333},[174,750,751],{"class":207},"Rostock",[174,753,346],{"class":333},[174,755,354],{"class":333},[174,757,759,761,764,766,768,770,773],{"class":176,"line":758},23,[174,760,697],{"class":333},[174,762,763],{"class":187},"country",[174,765,346],{"class":333},[174,767,204],{"class":333},[174,769,441],{"class":333},[174,771,772],{"class":207},"DE",[174,774,775],{"class":333},"\"\n",[174,777,779],{"class":176,"line":778},24,[174,780,781],{"class":333},"      },\n",[174,783,785,787,790,792,794,796,799,801],{"class":176,"line":784},25,[174,786,413],{"class":333},[174,788,789],{"class":416},"createdAt",[174,791,346],{"class":333},[174,793,204],{"class":333},[174,795,441],{"class":333},[174,797,798],{"class":207},"2026-03-14T09:12:04.000Z",[174,800,346],{"class":333},[174,802,354],{"class":333},[174,804,806,808,811,813,815,817,820],{"class":176,"line":805},26,[174,807,413],{"class":333},[174,809,810],{"class":416},"updatedAt",[174,812,346],{"class":333},[174,814,204],{"class":333},[174,816,441],{"class":333},[174,818,819],{"class":207},"2026-08-27T16:40:11.000Z",[174,821,775],{"class":333},[174,823,825],{"class":176,"line":824},27,[174,826,827],{"class":333},"    }\n",[174,829,831],{"class":176,"line":830},28,[174,832,833],{"class":333},"  ]\n",[174,835,837],{"class":176,"line":836},29,[174,838,839],{"class":333},"}\n",[11,841,842,843,314,846,314,849,852],{},"Daran hängt der Unterschied zu CSV, und er ist größer als die Schreibweise. Eine CSV-Zeile ist flach: ein Kunde, eine Zeile, feste Spalten. Der Kunde oben hat eine Liste von Telefonnummern, eine Liste von E-Mail-Adressen und eine Adresse als eigenes Objekt. In CSV wären das ",[45,844,845],{},"Telefon1",[45,847,848],{},"Telefon2",[45,850,851],{},"Telefon3"," und die Hoffnung, dass niemand eine vierte einträgt, oder eine zweite Datei mit Fremdschlüssel. In JSON ist es einfach eine Liste, und sie darf leer sein.",[11,854,855],{},"Wahrscheinlich kennst du XML besser als JSON, aus GAEB, DATANORM, UGL oder der XRechnung. Dann ist der Umstieg klein, denn die Aufgabe ist dieselbe: strukturierte Daten als Text. JSON lässt nur das weg, was beim Lesen und Schreiben Arbeit macht. Keine schließenden Tags, keine Entscheidung zwischen Attribut und Element, keine Namespaces, kein Schema, das du brauchst, um überhaupt an einen Wert zu kommen. Was in XML ein XPath-Ausdruck war, ist hier ein Zugriff auf einen Schlüssel im Wörterbuch.",[11,857,858,859,862],{},"Zwei Dinge, die daraus folgen: Ein JSON-Dokument ist bei gleichem Inhalt deutlich kürzer, und es gibt genau eine naheliegende Abbildung auf die Datenstrukturen deiner Sprache, nämlich Wörterbuch und Liste. Die Artesa-API antwortet ausschließlich in JSON, ein ",[45,860,861],{},"Accept: application\u002Fxml"," gibt es nicht.",[11,864,865],{},"Was aus der CSV-Welt kommend am häufigsten schiefgeht:",[119,867,869,883,899,915,921,935],{"type":868},"cross",[870,871,873],"checklist-item",{"title":872},"Zahl gegen Text",[11,874,875,878,879,882],{},[45,876,877],{},"\"id\": 4711"," ist eine Zahl, ",[45,880,881],{},"\"number\": \"K-1042\""," ein Text. Anführungszeichen um eine ID herum sind ein anderer Wert, nicht dieselbe ID in anderer Schreibweise.",[870,884,886],{"title":885},"null gegen leerer Text",[11,887,888,890,891,894,895,898],{},[45,889,317],{}," heißt „nicht gesetzt\", ",[45,892,893],{},"\"\""," heißt „gesetzt, und zwar leer\". Bei Feldern wie ",[45,896,897],{},"approvedAt"," entscheidet das darüber, ob ein Stundenzettel genehmigt ist oder nicht.",[870,900,902],{"title":901},"Datum immer ISO 8601",[11,903,904,906,907,910,911,914],{},[45,905,819],{}," statt ",[45,908,909],{},"27.08.2026",". Das ",[45,912,913],{},"Z"," am Ende heißt UTC, im Sommer also zwei Stunden vor der Uhr im Büro.",[870,916,918],{"title":917},"Kein Komma hinter dem letzten Eintrag",[11,919,920],{},"Ein Komma nach dem letzten Feld ist in JSON ungültig, auch wenn jeder Editor es durchlässt. Häufigster Fehler beim Zusammenbauen eines Bodys per String-Verkettung.",[870,922,924],{"title":923},"Keine Kommentare",[11,925,926,927,930,931,934],{},"JSON hat kein ",[45,928,929],{},"\u002F\u002F"," und kein ",[45,932,933],{},"#",". Was aussieht wie ein Kommentar in einer Doku, ist eine Auslassung und kein gültiges JSON.",[870,936,938],{"title":937},"Groß- und Kleinschreibung zählt",[11,939,940,942,943,946,947,950],{},[45,941,456],{}," ist nicht ",[45,944,945],{},"CompanyName"," und nicht ",[45,948,949],{},"companyname",". Anders als bei Spaltenüberschriften in Excel gibt es hier keine Nachsicht.",[11,952,953,954,957,958,961],{},"Diese Fehler entstehen fast alle an derselben Stelle: wenn JSON von Hand zusammengesetzt wird. Eine Verkettung wie ",[45,955,956],{},"\"{\" & Chr(34) & \"companyName\" & Chr(34) & \": \" & …"," läuft genau so lange, bis ein Kunde ein Anführungszeichen im Firmennamen hat, ein Feld leer bleibt oder in einer Adresse ein Zeilenumbruch steckt. Wir haben Bodys bekommen, in denen eine Liste in geschweiften statt in eckigen Klammern stand, und solche mit echten Zeilenumbrüchen mitten im Text, wo ein ",[45,959,960],{},"\\n"," hingehört.",[26,963,966,984,991,998],{"title":964,"type":965},"JSON nicht als Text zusammenbauen","danger",[11,967,968,969,972,973,976,977,276,980,983],{},"Zum Schreiben ein Objekt füllen und ",[18,970,971],{},"serialisieren lassen",", zum Lesen einmal ",[18,974,975],{},"parsen"," und auf Felder zugreifen. Nie mit ",[45,978,979],{},"Instr",[45,981,982],{},"Mid"," im Antworttext nach Werten suchen und nie einen Body per String-Verkettung erzeugen.",[11,985,986,987,990],{},"Jede Sprache hat dafür etwas Fertiges: VBA-JSON in VBA, ",[45,988,989],{},"System.Text.Json"," in .NET, Jackson in Java. Die Bibliothek kennt die Sonderfälle, die beim Verketten durchrutschen: Anführungszeichen im Wert, Umlaute, Zeilenumbrüche, das Komma hinter dem letzten Feld.",[11,992,993,994,997],{},"Und wenn ein Body trotzdem abgelehnt wird, ist der erste Griff ein Validator statt der Fehlermeldung: ",[81,995,92],{"href":90,"rel":996},[85]," zeigt die Zeile, in der die Klammer fehlt.",[11,999,1000,1001,1006],{},"Für den Umstieg im Kopf hilft derselbe Dienst mit einem ",[81,1002,1005],{"href":1003,"rel":1004},"https:\u002F\u002Fjsonlint.com\u002Fcsv-to-json",[85],"CSV-to-JSON-Konverter",": Wirf eine deiner Exportdateien hinein und schau, wie dieselben Daten in JSON aussehen.",[11,1008,1009,1010,1015,1016,1021,1022,93],{},"Die Spezifikation dahinter ist kurz genug, um sie einmal zu lesen: ",[81,1011,1014],{"href":1012,"rel":1013},"https:\u002F\u002Fwww.json.org\u002Fjson-de.html",[85],"json.org"," auf einer Seite, formal in ",[81,1017,1020],{"href":1018,"rel":1019},"https:\u002F\u002Fwww.rfc-editor.org\u002Frfc\u002Frfc8259.html",[85],"RFC 8259",". Für den Alltag reicht ",[81,1023,1026],{"href":1024,"rel":1025},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fde\u002Fdocs\u002FLearn_web_development\u002FCore\u002FScripting\u002FJSON",[85],"die JSON-Seite bei MDN",[95,1028,1030],{"id":1029},"die-http-methoden-get-post-patch-und-delete","Die HTTP-Methoden: GET, POST, PATCH und DELETE",[11,1032,1033],{},"Vier Verben decken alles ab, was eine Anbindung tut:",[1035,1036,1037,1053],"table",{},[1038,1039,1040],"thead",{},[1041,1042,1043,1047,1050],"tr",{},[1044,1045,1046],"th",{},"Was du willst",[1044,1048,1049],{},"Request",[1044,1051,1052],{},"Antwort",[1054,1055,1056,1075,1090,1109,1124],"tbody",{},[1041,1057,1058,1062,1067],{},[1059,1060,1061],"td",{},"Kundenliste lesen",[1059,1063,1064],{},[45,1065,1066],{},"GET \u002Fv1\u002Fcustomers",[1059,1068,1069,1072,1073],{},[45,1070,1071],{},"200"," und eine Seite mit ",[45,1074,394],{},[1041,1076,1077,1080,1085],{},[1059,1078,1079],{},"Einen Kunden lesen",[1059,1081,1082],{},[45,1083,1084],{},"GET \u002Fv1\u002Fcustomers\u002F4711",[1059,1086,1087,1089],{},[45,1088,1071],{}," und das Objekt",[1041,1091,1092,1095,1101],{},[1059,1093,1094],{},"Kunden anlegen",[1059,1096,1097,1100],{},[45,1098,1099],{},"POST \u002Fv1\u002Fcustomers"," mit Body",[1059,1102,1103,1106,1107],{},[45,1104,1105],{},"201"," und das neue Objekt samt ",[45,1108,417],{},[1041,1110,1111,1114,1119],{},[1059,1112,1113],{},"Kunden ändern",[1059,1115,1116,1100],{},[45,1117,1118],{},"PATCH \u002Fv1\u002Fcustomers\u002F4711",[1059,1120,1121,1123],{},[45,1122,1071],{}," und das geänderte Objekt",[1041,1125,1126,1129,1134],{},[1059,1127,1128],{},"Kunden löschen",[1059,1130,1131],{},[45,1132,1133],{},"DELETE \u002Fv1\u002Fcustomers\u002F4711",[1059,1135,1136,1139],{},[45,1137,1138],{},"204",", kein Body",[11,1141,1142,1143,1145,1146,1149],{},"Wichtig an ",[45,1144,55],{},": Du schickst ",[18,1147,1148],{},"nur die Felder, die sich ändern sollen."," Ein Body mit einem einzigen Feld ist der Normalfall, alles andere am Datensatz bleibt, wie es war. Der Reflex aus der Datenbankwelt, erst den ganzen Satz zu lesen, ein Feld zu ändern und alles zurückzuschreiben, ist hier nicht nur unnötig, er überschreibt dir womöglich, was in der Zwischenzeit jemand im Büro eingetippt hat.",[95,1151,1153],{"id":1152},"authentifizierung-api-schlüssel-als-bearer-token-im-header","Authentifizierung: API-Schlüssel als Bearer Token im Header",[11,1155,1156,1157,1160],{},"Der Header ist die Stelle für alles, was ",[18,1158,1159],{},"über"," den Request etwas sagt, statt Teil der Daten zu sein. Die Authentifizierung sitzt genau deshalb dort und nicht als Parameter in der URL: URLs landen überall. Im Browserverlauf, im Proxy-Log, im Webserver-Log, in der Fehlermeldung, die dir jemand als Screenshot ins Ticket hängt.",[11,1162,1163],{},"Bei Artesa sieht die Zeile so aus:",[165,1165,1167],{"className":167,"code":1166,"language":169,"meta":170,"style":170},"Authorization: Bearer dein-api-schluessel\n",[45,1168,1169],{"__ignoreMap":170},[174,1170,1171,1173,1175],{"class":176,"line":177},[174,1172,72],{"class":200},[174,1174,204],{"class":187},[174,1176,218],{"class":207},[11,1178,1179,1182],{},[45,1180,1181],{},"Bearer"," heißt Inhaber, und das ist wörtlich gemeint: Es gibt keinen Benutzernamen, kein Passwort und keine Anmeldung davor. Wer den Schlüssel hat, darf alles, was der Schlüssel darf. Er gehört dem Unternehmen, nicht einem einzelnen Benutzer, und er läuft nicht von sich aus ab. Behandle ihn wie ein Passwort, nicht wie eine Kundennummer. Den Schlüssel selbst bekommst du bei uns auf Anfrage.",[11,1184,1185,1186,1189],{},"Fehlt der Header oder ist der Schlüssel falsch, antwortet die API mit ",[45,1187,1188],{},"401"," und rührt nichts an.",[26,1191,1194,1224],{"title":1192,"type":1193},"Wo der Schlüssel nicht hingehört","warning",[31,1195,1196,1206,1212,1218],{},[34,1197,1198,1201,1202,1205],{},[18,1199,1200],{},"Nicht in die URL."," Kein ",[45,1203,1204],{},"?apikey=...",", aus den Gründen oben.",[34,1207,1208,1211],{},[18,1209,1210],{},"Nicht in den Quellcode."," Eine Konstante im VBA-Modul wandert mit der Datei durch den halben Betrieb.",[34,1213,1214,1217],{},[18,1215,1216],{},"Nicht ins Repository."," Auch nicht „nur kurz zum Testen\", denn die Historie behält ihn.",[34,1219,1220,1223],{},[18,1221,1222],{},"Nicht in die Excel-Datei",", die per Mail rumgeht.",[11,1225,1226,1227,1230,1231,93],{},"Stattdessen: eine Konfigurationsdatei neben der Anwendung, eine Umgebungsvariable oder die Registry, in jedem Fall außerhalb dessen, was verteilt oder eingecheckt wird. Und immer über ",[45,1228,1229],{},"https",", nie über ",[45,1232,169],{},[95,1234,1236],{"id":1235},"daten-abrufen-filter-und-pagination","Daten abrufen: Filter und Pagination",[11,1238,1239,1240,1242,1243,314,1246,1248,1249,1252],{},"Listen kommen seitenweise, und die Seite ist klein. ",[45,1241,343],{}," zählt ab ",[45,1244,1245],{},"0",[45,1247,377],{}," liegt standardmäßig bei 10 und ",[18,1250,1251],{},"maximal bei 20",". Wer 800 Kunden abholen will, blättert also durch 40 Seiten. Wie viele es sind, sagt die Antwort selbst:",[165,1254,1256],{"className":324,"code":1255,"language":326,"meta":170,"style":170},"{ \"page\": 0, \"pages\": 12, \"size\": 20, \"items\": [] }\n",[45,1257,1258],{"__ignoreMap":170},[174,1259,1260,1263,1265,1267,1269,1271,1273,1275,1277,1279,1281,1283,1285,1287,1289,1291,1293,1295,1297,1299,1301,1303,1305,1307,1310],{"class":176,"line":177},[174,1261,1262],{"class":333},"{",[174,1264,441],{"class":333},[174,1266,343],{"class":342},[174,1268,346],{"class":333},[174,1270,204],{"class":333},[174,1272,351],{"class":187},[174,1274,571],{"class":333},[174,1276,441],{"class":333},[174,1278,361],{"class":342},[174,1280,346],{"class":333},[174,1282,204],{"class":333},[174,1284,368],{"class":187},[174,1286,571],{"class":333},[174,1288,441],{"class":333},[174,1290,377],{"class":342},[174,1292,346],{"class":333},[174,1294,204],{"class":333},[174,1296,384],{"class":187},[174,1298,571],{"class":333},[174,1300,441],{"class":333},[174,1302,394],{"class":342},[174,1304,346],{"class":333},[174,1306,204],{"class":333},[174,1308,1309],{"class":333}," []",[174,1311,602],{"class":333},[11,1313,1314,1315,1317,1318,1320],{},"Du liest also ",[45,1316,361],{}," aus der ersten Antwort und zählst ",[45,1319,343],{}," hoch, bis du durch bist. Zum Filtern hängst du Bedingungen an die URL:",[1035,1322,1323,1336],{},[1038,1324,1325],{},[1041,1326,1327,1330,1333],{},[1044,1328,1329],{},"Operator",[1044,1331,1332],{},"Bedeutung",[1044,1334,1335],{},"Beispiel",[1054,1337,1338,1351,1370,1388,1403],{},[1041,1339,1340,1343,1346],{},[1059,1341,1342],{},"ohne",[1059,1344,1345],{},"genau dieser Wert",[1059,1347,1348],{},[45,1349,1350],{},"?assignmentId=123",[1041,1352,1353,1362,1365],{},[1059,1354,1355,1358,1359],{},[45,1356,1357],{},"[$gt]"," \u002F ",[45,1360,1361],{},"[$gte]",[1059,1363,1364],{},"größer \u002F größer oder gleich",[1059,1366,1367],{},[45,1368,1369],{},"?updatedAt[$gt]=2026-09-01T00:00:00Z",[1041,1371,1372,1380,1383],{},[1059,1373,1374,1358,1377],{},[45,1375,1376],{},"[$lt]",[45,1378,1379],{},"[$lte]",[1059,1381,1382],{},"kleiner \u002F kleiner oder gleich",[1059,1384,1385],{},[45,1386,1387],{},"?updatedAt[$lt]=2026-09-02T00:00:00Z",[1041,1389,1390,1395,1398],{},[1059,1391,1392],{},[45,1393,1394],{},"[$ne]",[1059,1396,1397],{},"ungleich",[1059,1399,1400],{},[45,1401,1402],{},"?submittedAt[$ne]=null",[1041,1404,1405,1413,1416],{},[1059,1406,1407,1358,1410],{},[45,1408,1409],{},"[$in]",[45,1411,1412],{},"[$nin]",[1059,1414,1415],{},"in \u002F nicht in einer Liste, bis 100 Werte",[1059,1417,1418],{},[45,1419,1420],{},"?assignmentId[$in]=123,456,789",[11,1422,1423,1424,1426,1427,1431],{},"Mehrere Bedingungen im selben Aufruf werden mit UND verknüpft, und ",[45,1425,317],{}," schreibst du als Wort, wo es wirklich „leer\" heißen soll. Damit wird das Filtern zum eigentlichen Werkzeug, und hier liegt der größte Unterschied zum Datei-Export: Du holst nicht alles ab und sortierst hinterher in Access, sondern stellst die Frage direkt an die API. Welche Felder ein Endpunkt filtern kann, listet seine Doku unter ",[1428,1429,1430],"em",{},"Query Parameters",", und jedes davon nimmt die Operatoren aus der Tabelle:",[165,1433,1435],{"className":167,"code":1434,"language":169,"meta":170,"style":170},"GET \u002Fv1\u002Fcustomers?externalId=ACC-90231\nGET \u002Fv1\u002Fcustomers?updatedAt[$gt]=2026-09-01T22:00:00Z&size=20\nGET \u002Fv1\u002Ftime-sheet-days?submittedAt[$ne]=null&approvedAt=null\nGET \u002Fv1\u002Fassignment-events?assignmentId[$in]=4711,4712,4713\nGET \u002Fv1\u002Ftime-entries?eventId[$in]=null,123\n",[45,1436,1437,1444,1451,1458,1465],{"__ignoreMap":170},[174,1438,1439,1441],{"class":176,"line":177},[174,1440,47],{"class":180},[174,1442,1443],{"class":183}," \u002Fv1\u002Fcustomers?externalId=ACC-90231\n",[174,1445,1446,1448],{"class":176,"line":197},[174,1447,47],{"class":180},[174,1449,1450],{"class":183}," \u002Fv1\u002Fcustomers?updatedAt[$gt]=2026-09-01T22:00:00Z&size=20\n",[174,1452,1453,1455],{"class":176,"line":211},[174,1454,47],{"class":180},[174,1456,1457],{"class":183}," \u002Fv1\u002Ftime-sheet-days?submittedAt[$ne]=null&approvedAt=null\n",[174,1459,1460,1462],{"class":176,"line":221},[174,1461,47],{"class":180},[174,1463,1464],{"class":183}," \u002Fv1\u002Fassignment-events?assignmentId[$in]=4711,4712,4713\n",[174,1466,1467,1469],{"class":176,"line":389},[174,1468,47],{"class":180},[174,1470,1471],{"class":183}," \u002Fv1\u002Ftime-entries?eventId[$in]=null,123\n",[11,1473,1474],{},"Der Reihe nach: einen Kunden über die eigene Nummer aus dem Altsystem finden, alles Geänderte seit dem letzten Lauf, die Stundenzettel-Tage, die abgegeben aber noch nicht genehmigt sind, die Arbeitsschritte zu drei Aufträgen auf einmal, und Zeiteinträge mit oder ohne Arbeitsschritt. Nichts davon braucht Nachbearbeitung auf deiner Seite, und jede Bedingung, die in der URL steht, spart Seiten, die du sonst durchblättern müsstest.",[11,1476,1477],{},"Daraus ergibt sich der wichtigste Handgriff der ganzen Anbindung. Du holst nicht jede Nacht alles, sondern nur, was sich seit dem letzten Lauf geändert hat:",[165,1479,1481],{"className":167,"code":1480,"language":169,"meta":170,"style":170},"GET \u002Fv1\u002Ftime-entries?updatedAt[$gt]=2026-09-01T22:00:00Z&size=20&page=0 HTTP\u002F1.1\nHost: api.artesa.de\nAuthorization: Bearer dein-api-schluessel\n",[45,1482,1483,1496,1504],{"__ignoreMap":170},[174,1484,1485,1487,1490,1492,1494],{"class":176,"line":177},[174,1486,47],{"class":180},[174,1488,1489],{"class":183}," \u002Fv1\u002Ftime-entries?updatedAt[$gt]=2026-09-01T22:00:00Z&size=20&page=0 ",[174,1491,188],{"class":187},[174,1493,191],{"class":183},[174,1495,194],{"class":187},[174,1497,1498,1500,1502],{"class":176,"line":197},[174,1499,201],{"class":200},[174,1501,204],{"class":187},[174,1503,208],{"class":207},[174,1505,1506,1508,1510],{"class":176,"line":211},[174,1507,72],{"class":200},[174,1509,204],{"class":187},[174,1511,218],{"class":207},[11,1513,1514,1515,1518],{},"Zwei Dinge, die dabei zu beachten sind: Der Zeitstempel ist UTC, die ",[45,1516,1517],{},"22:00:00Z"," sind im Sommer also Mitternacht deutscher Zeit. Und setze die Grenze ein paar Minuten vor dem letzten Lauf statt exakt darauf, sonst fällt dir irgendwann ein Datensatz durch, der genau in der Sekunde geschrieben wurde, in der du gefragt hast.",[11,1520,1521,1522,1526,1527,1531,1532,1536],{},"Was du auf diesem Weg abholen kannst, geht über Kunden und Aufträge hinaus: Zeiteinträge, Abwesenheiten und die ",[81,1523,1525],{"href":1524},"\u002Fzeiterfassung\u002Fstundenzettel","Stundenzettel"," als fertig gerechnete Summen pro Tag, Woche und Monat, jeweils mit dem Genehmigungsstatus. Für eine ",[81,1528,1530],{"href":1529},"\u002Fzeiterfassung\u002Fnachkalkulation","Nachkalkulation"," oder die Übergabe an die Lohnabrechnung ist das die Quelle, die du willst, statt einzelne Buchungen selbst zu summieren. Erfasst werden sie vorher in der ",[81,1533,1535],{"href":1534},"\u002Fzeiterfassung\u002Fprojektzeiterfassung","Projektzeiterfassung",", auf dem Handy am Auftrag.",[95,1538,1540],{"id":1539},"daten-schreiben-anlegen-ändern-und-doubletten-vermeiden","Daten schreiben: anlegen, ändern und Doubletten vermeiden",[11,1542,1543,1544,1546,1547,1549],{},"Ein ",[45,1545,51],{}," schickt das Objekt als JSON im Body, ohne ",[45,1548,417],{},", denn die vergibt die API:",[165,1551,1553],{"className":324,"code":1552,"language":326,"meta":170,"style":170},"{\n  \"companyName\": \"Metallbau Sander GmbH\",\n  \"externalId\": \"ACC-90231\",\n  \"salutation\": \"Herr\",\n  \"firstName\": \"Jens\",\n  \"surname\": \"Sander\",\n  \"emails\": [\n    { \"label\": \"main\", \"isDefault\": true, \"emailAddress\": \"info@metallbau-sander.de\" }\n  ],\n  \"billingAddress\": {\n    \"street\": \"Werftstraße 12\",\n    \"zip\": \"18057\",\n    \"city\": \"Rostock\",\n    \"country\": \"DE\"\n  }\n}\n",[45,1554,1555,1559,1577,1595,1615,1633,1651,1663,1710,1715,1727,1746,1764,1782,1798,1803],{"__ignoreMap":170},[174,1556,1557],{"class":176,"line":177},[174,1558,334],{"class":333},[174,1560,1561,1563,1565,1567,1569,1571,1573,1575],{"class":176,"line":197},[174,1562,339],{"class":333},[174,1564,456],{"class":342},[174,1566,346],{"class":333},[174,1568,204],{"class":333},[174,1570,441],{"class":333},[174,1572,465],{"class":207},[174,1574,346],{"class":333},[174,1576,354],{"class":333},[174,1578,1579,1581,1583,1585,1587,1589,1591,1593],{"class":176,"line":211},[174,1580,339],{"class":333},[174,1582,477],{"class":342},[174,1584,346],{"class":333},[174,1586,204],{"class":333},[174,1588,441],{"class":333},[174,1590,486],{"class":207},[174,1592,346],{"class":333},[174,1594,354],{"class":333},[174,1596,1597,1599,1602,1604,1606,1608,1611,1613],{"class":176,"line":221},[174,1598,339],{"class":333},[174,1600,1601],{"class":342},"salutation",[174,1603,346],{"class":333},[174,1605,204],{"class":333},[174,1607,441],{"class":333},[174,1609,1610],{"class":207},"Herr",[174,1612,346],{"class":333},[174,1614,354],{"class":333},[174,1616,1617,1619,1621,1623,1625,1627,1629,1631],{"class":176,"line":389},[174,1618,339],{"class":333},[174,1620,498],{"class":342},[174,1622,346],{"class":333},[174,1624,204],{"class":333},[174,1626,441],{"class":333},[174,1628,507],{"class":207},[174,1630,346],{"class":333},[174,1632,354],{"class":333},[174,1634,1635,1637,1639,1641,1643,1645,1647,1649],{"class":176,"line":404},[174,1636,339],{"class":333},[174,1638,519],{"class":342},[174,1640,346],{"class":333},[174,1642,204],{"class":333},[174,1644,441],{"class":333},[174,1646,528],{"class":207},[174,1648,346],{"class":333},[174,1650,354],{"class":333},[174,1652,1653,1655,1657,1659,1661],{"class":176,"line":410},[174,1654,339],{"class":333},[174,1656,616],{"class":342},[174,1658,346],{"class":333},[174,1660,204],{"class":333},[174,1662,401],{"class":333},[174,1664,1665,1668,1670,1672,1674,1676,1678,1680,1682,1684,1686,1688,1690,1692,1694,1696,1698,1700,1702,1704,1706,1708],{"class":176,"line":429},[174,1666,1667],{"class":333},"    {",[174,1669,441],{"class":333},[174,1671,557],{"class":416},[174,1673,346],{"class":333},[174,1675,204],{"class":333},[174,1677,441],{"class":333},[174,1679,566],{"class":207},[174,1681,346],{"class":333},[174,1683,571],{"class":333},[174,1685,441],{"class":333},[174,1687,576],{"class":416},[174,1689,346],{"class":333},[174,1691,204],{"class":333},[174,1693,583],{"class":333},[174,1695,441],{"class":333},[174,1697,658],{"class":416},[174,1699,346],{"class":333},[174,1701,204],{"class":333},[174,1703,441],{"class":333},[174,1705,667],{"class":207},[174,1707,346],{"class":333},[174,1709,602],{"class":333},[174,1711,1712],{"class":176,"line":451},[174,1713,1714],{"class":333},"  ],\n",[174,1716,1717,1719,1721,1723,1725],{"class":176,"line":472},[174,1718,339],{"class":333},[174,1720,684],{"class":342},[174,1722,346],{"class":333},[174,1724,204],{"class":333},[174,1726,691],{"class":333},[174,1728,1729,1732,1734,1736,1738,1740,1742,1744],{"class":176,"line":493},[174,1730,1731],{"class":333},"    \"",[174,1733,700],{"class":416},[174,1735,346],{"class":333},[174,1737,204],{"class":333},[174,1739,441],{"class":333},[174,1741,709],{"class":207},[174,1743,346],{"class":333},[174,1745,354],{"class":333},[174,1747,1748,1750,1752,1754,1756,1758,1760,1762],{"class":176,"line":514},[174,1749,1731],{"class":333},[174,1751,721],{"class":416},[174,1753,346],{"class":333},[174,1755,204],{"class":333},[174,1757,441],{"class":333},[174,1759,730],{"class":207},[174,1761,346],{"class":333},[174,1763,354],{"class":333},[174,1765,1766,1768,1770,1772,1774,1776,1778,1780],{"class":176,"line":535},[174,1767,1731],{"class":333},[174,1769,742],{"class":416},[174,1771,346],{"class":333},[174,1773,204],{"class":333},[174,1775,441],{"class":333},[174,1777,751],{"class":207},[174,1779,346],{"class":333},[174,1781,354],{"class":333},[174,1783,1784,1786,1788,1790,1792,1794,1796],{"class":176,"line":549},[174,1785,1731],{"class":333},[174,1787,763],{"class":416},[174,1789,346],{"class":333},[174,1791,204],{"class":333},[174,1793,441],{"class":333},[174,1795,772],{"class":207},[174,1797,775],{"class":333},[174,1799,1800],{"class":176,"line":605},[174,1801,1802],{"class":333},"  }\n",[174,1804,1805],{"class":176,"line":611},[174,1806,839],{"class":333},[11,1808,1809,1810,1812,1813,1815,1816,314,1818,276,1820,1822,1823,1825,1826,1828],{},"Zurück kommt ",[45,1811,1105],{}," und derselbe Datensatz mit ",[45,1814,417],{},". Anders als ",[45,1817,47],{},[45,1819,55],{},[45,1821,59],{}," lässt sich ein ",[45,1824,51],{}," aber nicht gefahrlos wiederholen: Läuft dein Job zweimal, oder bricht er nach dem Anlegen und vor dem Merken der ",[45,1827,417],{}," ab, steht der Kunde zweimal drin. Eine Schnittstelle, die das nicht abfängt, produziert Doubletten, und zwar genau dann, wenn niemand hinschaut.",[11,1830,1831,1832,1834,1835,1837],{},"Das Feld dafür ist ",[45,1833,477],{},". Dort schreibst du den Schlüssel aus deinem System hinein, die Kundennummer aus dem ERP oder den Primärschlüssel aus der Access-Tabelle. Damit lässt sich jeder Datensatz wiederfinden, ohne dass du dir die Artesa-",[45,1836,417],{}," merken musst:",[165,1839,1841],{"className":167,"code":1840,"language":169,"meta":170,"style":170},"GET \u002Fv1\u002Fcustomers?externalId=ACC-90231\n",[45,1842,1843],{"__ignoreMap":170},[174,1844,1845,1847],{"class":176,"line":177},[174,1846,47],{"class":180},[174,1848,1443],{"class":183},[11,1850,1851,1852,1854,1855,1857,1858,1860,1861,1863],{},"Kommt eine leere ",[45,1853,394],{},"-Liste zurück, legst du mit ",[45,1856,51],{}," an. Kommt ein Datensatz, änderst du ihn mit ",[45,1859,55],{}," auf dessen ",[45,1862,417],{},". Dieselben zwei Schritte für jeden Lauf, egal ob es der erste ist.",[26,1865,1867],{"title":1866,"type":29},"Praxistipp",[11,1868,1869,1870,1872,1873,1875],{},"Schreib die ",[45,1871,477],{}," von der ersten Zeile an mit, auch wenn du sie heute nicht brauchst. Nachträglich zuzuordnen heißt, 800 Kunden über Firmenname und Postleitzahl zu vergleichen, und das geht nie ganz auf. Adressen tragen ebenfalls eine ",[45,1874,477],{},", sodass auch die Zuordnung von Lieferadressen erhalten bleibt.",[11,1877,1878,1879,1883,1884,1888],{},"Auf derselben Logik laufen Aufträge und Arbeitsschritte. Im Betrieb sammelt die ",[81,1880,1882],{"href":1881},"\u002Fauftragsverwaltung\u002Fauftragsakte","Auftragsakte"," danach alles, was am Auftrag hängt: Termine, Status, Zeiten und Dokumente. Das ist auch der Grund, warum die Anbindung meist in dieser Richtung gebaut wird: Ein ",[81,1885,1887],{"href":1886},"\u002Fgewerke\u002Fmetallbauer","Metallbaubetrieb"," kalkuliert weiter in seinem Programm und schiebt den fertigen Auftrag samt Kunde nach Artesa, wo daraus Planung, Zeiten und Doku entstehen.",[95,1890,1892],{"id":1891},"fehler-behandeln-die-statuscodes-400-401-und-404","Fehler behandeln: die Statuscodes 400, 401 und 404",[11,1894,1895],{},"Fehler kommen mit dem Statuscode und einem Body in immer derselben Form:",[165,1897,1899],{"className":324,"code":1898,"language":326,"meta":170,"style":170},"{\n  \"name\": \"BadRequest\",\n  \"message\": \"Invalid query: \\\"createdAt\\\": Expected a valid ISO 8601 date-time string\",\n  \"code\": 400\n}\n",[45,1900,1901,1905,1925,1955,1968],{"__ignoreMap":170},[174,1902,1903],{"class":176,"line":177},[174,1904,334],{"class":333},[174,1906,1907,1909,1912,1914,1916,1918,1921,1923],{"class":176,"line":197},[174,1908,339],{"class":333},[174,1910,1911],{"class":342},"name",[174,1913,346],{"class":333},[174,1915,204],{"class":333},[174,1917,441],{"class":333},[174,1919,1920],{"class":207},"BadRequest",[174,1922,346],{"class":333},[174,1924,354],{"class":333},[174,1926,1927,1929,1932,1934,1936,1938,1941,1944,1946,1948,1951,1953],{"class":176,"line":211},[174,1928,339],{"class":333},[174,1930,1931],{"class":342},"message",[174,1933,346],{"class":333},[174,1935,204],{"class":333},[174,1937,441],{"class":333},[174,1939,1940],{"class":207},"Invalid query: ",[174,1942,1943],{"class":183},"\\\"",[174,1945,789],{"class":207},[174,1947,1943],{"class":183},[174,1949,1950],{"class":207},": Expected a valid ISO 8601 date-time string",[174,1952,346],{"class":333},[174,1954,354],{"class":333},[174,1956,1957,1959,1961,1963,1965],{"class":176,"line":221},[174,1958,339],{"class":333},[174,1960,45],{"class":342},[174,1962,346],{"class":333},[174,1964,204],{"class":333},[174,1966,1967],{"class":187}," 400\n",[174,1969,1970],{"class":176,"line":389},[174,1971,839],{"class":333},[11,1973,1974,1975,1977,1978,93],{},"Die ",[45,1976,1931],{}," sagt in der Regel genau, welches Feld nicht passt. Bei Validierungsfehlern stehen die betroffenen Felder zusätzlich einzeln unter ",[45,1979,1980],{},"data.validationErrors",[1035,1982,1983,1996],{},[1038,1984,1985],{},[1041,1986,1987,1990,1993],{},[1044,1988,1989],{},"Code",[1044,1991,1992],{},"Heißt",[1044,1994,1995],{},"Was zu tun ist",[1054,1997,1998,2014,2030,2046],{},[1041,1999,2000,2005,2008],{},[1059,2001,2002],{},[45,2003,2004],{},"400",[1059,2006,2007],{},"Anfrage ist falsch gebaut",[1059,2009,2010,2011,2013],{},"Nicht wiederholen, die ",[45,2012,1931],{}," lesen. Wiederholen ändert nichts.",[1041,2015,2016,2020,2023],{},[1059,2017,2018],{},[45,2019,1188],{},[1059,2021,2022],{},"Schlüssel fehlt oder ist falsch",[1059,2024,2025,2026,2029],{},"Header prüfen, ",[45,2027,2028],{},"Bearer "," mit Leerzeichen davor.",[1041,2031,2032,2037,2040],{},[1059,2033,2034],{},[45,2035,2036],{},"404",[1059,2038,2039],{},"Gibt es nicht, oder nicht für dich",[1059,2041,2042,2043,2045],{},"Falsche ",[45,2044,417],{},", oder der Datensatz gehört zu einem anderen Unternehmen.",[1041,2047,2048,2053,2056],{},[1059,2049,2050],{},[45,2051,2052],{},"5xx",[1059,2054,2055],{},"Problem auf unserer Seite",[1059,2057,2058],{},"Wiederholen, aber mit steigendem Abstand statt in der Schleife.",[11,2060,2061,2062,276,2064,2066],{},"Der eine Fehler, der jede Anbindung irgendwann kostet: Statuscode nicht prüfen und einfach den Body parsen. Dann steht in deiner Zieltabelle eine Fehlermeldung, wo ein Kunde stehen sollte, und niemand merkt es. Prüf den Code vor dem Parsen, und schreib ",[45,2063,45],{},[45,2065,1931],{}," ins Log.",[95,2068,2070],{"id":2069},"openapi-3-1-spezifikation-abrufen-und-client-generieren","OpenAPI 3.1: Spezifikation abrufen und Client generieren",[11,2072,2073],{},"Die Schnittstelle ist nicht nur dokumentiert, sie ist beschrieben. Jede Ressource liefert ihre eigene Spezifikation nach OpenAPI 3.1 als JSON, und dafür brauchst du nicht einmal einen Schlüssel:",[165,2075,2077],{"className":167,"code":2076,"language":169,"meta":170,"style":170},"GET \u002Fv1\u002Fcustomers\u002Fspec\nGET \u002Fv1\u002Ftime-entries\u002Fspec\n",[45,2078,2079,2086],{"__ignoreMap":170},[174,2080,2081,2083],{"class":176,"line":177},[174,2082,47],{"class":180},[174,2084,2085],{"class":183}," \u002Fv1\u002Fcustomers\u002Fspec\n",[174,2087,2088,2090],{"class":176,"line":197},[174,2089,47],{"class":180},[174,2091,2092],{"class":183}," \u002Fv1\u002Ftime-entries\u002Fspec\n",[11,2094,2095],{},"Drin steht, welche Felder es gibt, welchen Typ sie haben, welche Pflicht sind und welche Werte erlaubt sind, dazu getrennte Schemas fürs Anlegen, fürs Ändern und fürs Lesen. Das ist der Unterschied zwischen „beim Anlegen darf das mitkommen\" und „das darfst du nachträglich ändern\", und du musst ihn nicht raten.",[11,2097,2098],{},"Zwei Dinge machst du damit. Erstens: in Postman oder Insomnia importieren, dann stehen alle Aufrufe fertig da, statt dass du sie abtippst. Zweitens: einen typisierten Client generieren, in .NET mit NSwag oder Kiota, in Java mit dem OpenAPI Generator. Das ersetzt die Records, die du sonst von Hand pflegst, und wenn ein Feld dazukommt, generierst du neu, statt einen Changelog zu vergleichen.",[11,2100,2101,2102,2105,2106,2108,2109,2111],{},"Und der Punkt, der aus der Datei-Welt kommend am meisten wert ist: ",[18,2103,2104],{},"Die API validiert jede Anfrage gegen genau dieses Schema."," Ein Text, wo eine Zahl hingehört, ein fehlendes Pflichtfeld, ein Datum, das nicht ISO 8601 ist, ein Wert außerhalb der erlaubten Liste, all das wird mit ",[45,2107,2004],{}," abgelehnt, und die betroffenen Felder stehen einzeln unter ",[45,2110,1980],{},". Ein CSV-Import nimmt in derselben Lage, was er bekommt, und die Sache fällt in der Lohnabrechnung auf. Hier fällt sie in der Sekunde des Aufrufs auf, in deinem Log, mit Feldnamen.",[95,2113,2115],{"id":2114},"die-zwei-richtungen-einer-schnittstelle-zur-handwerkersoftware","Die zwei Richtungen einer Schnittstelle zur Handwerkersoftware",[11,2117,2118],{},"Bei aller Freiheit, die eine offene Schnittstelle lässt, sehen die Anbindungen in der Praxis überraschend gleich aus. Fast jede besteht aus denselben zwei Richtungen:",[106,2120,2122,2145],{":margin-y":108,":padding-x":109,"columns":110,"max-width":111,"align":2121},"stretch",[113,2123,2126,2129],{"icon":2124,"title":2125,"type":117,":prose":108},"tabler:arrow-right","Hin: Stamm- und Aufträge",[11,2127,2128],{},"Kunden, Aufträge und Arbeitsschritte entstehen im Bestandssystem, weil dort kalkuliert und fakturiert wird. Nach Artesa wandern sie, damit daraus Planung, Zeiten und Dokumentation werden.",[11,2130,2131,2132,276,2134,2136,2137,314,2139,276,2142,93],{},"Technisch sind das ",[45,2133,51],{},[45,2135,55],{}," auf ",[45,2138,155],{},[45,2140,2141],{},"\u002Fv1\u002Fassignments",[45,2143,2144],{},"\u002Fv1\u002Fassignment-events",[113,2146,2149,2152],{"icon":2147,"title":2148,"type":126,":prose":108},"tabler:arrow-left","Zurück: Arbeitszeiten",[11,2150,2151],{},"Die erfassten Stunden gehen ins Bestandssystem zurück, für Nachkalkulation und Lohnabrechnung.",[11,2153,2154,2155,2158],{},"Das ist reines Lesen über ",[45,2156,2157],{},"\u002Fv1\u002Ftime-entries"," und die Stundenzettel nach Tag, Woche und Monat, jeweils mit dem Genehmigungsstatus.",[26,2160,2163,2170],{"title":2161,"type":2162},"Baust du die Anbindung für mehrere Betriebe?","info",[11,2164,2165,2166,2169],{},"Dann sag uns das, denn dann lohnt sich Arbeit auf unserer Seite. Für die Hin-Richtung bauen wir einen eigenen Endpunkt, der Stamm- und Auftragsdaten in ",[18,2167,2168],{},"einem"," Aufruf annimmt, statt dass du drei Ressourcen einzeln bedienst und die Reihenfolge der Abhängigkeiten selbst sortierst.",[11,2171,2172],{},"Für die Rück-Richtung sprechen wir das Format ab und legen die Datei dort ab, wo dein System sie ohnehin abholt, etwa in OneDrive oder SharePoint. Dann musst du auf deiner Seite gar nichts gegen HTTP bauen.",[11,2174,2175,2176,2179],{},"Erzähl uns in einer Viertelstunde am Telefon, welches System auf der anderen Seite steht und welche der zwei Richtungen du brauchst. Dann sagen wir dir, was ",[45,2177,2178],{},"v1"," heute schon abdeckt und ob sich für deinen Fall ein eigener Endpunkt lohnt.",[2181,2182],"cta-buttons",{},[95,2184,2186],{"id":2185},"api-client-die-schnittstelle-testen-bevor-du-code-schreibst","API-Client: die Schnittstelle testen, bevor du Code schreibst",[11,2188,2189,2190,2193],{},"Der erste Aufruf gehört nicht in dein Programm, sondern in einen API-Client. Das ist ein Werkzeug, in dem du einen Request von Hand zusammensetzt, also Methode, URL, Header und Body einträgst, ihn abschickst und die Antwort im Rohzustand siehst. ",[81,2191,86],{"href":83,"rel":2192},[85]," ist der bekannteste, Bruno und Insomnia machen dasselbe, und für VS Code gibt es Erweiterungen, die reichen.",[11,2195,2196],{},"Der Grund, warum das am Anfang wichtiger ist als später: Es trennt zwei Fehlerquellen, die sonst gemeinsam auftreten. Läuft der Aufruf im Client und in deinem Programm nicht, liegt es an deinem Code. Läuft er im Client auch nicht, liegt es an URL, Schlüssel, Rechten oder Body, und du suchst an der richtigen Stelle. Ohne diesen Zwischenschritt debuggst du beides gleichzeitig, und genau das ist der Grund, warum eine erste Anbindung gern zwei Tage kostet statt zwei Stunden.",[11,2198,2199],{},"Drei Dinge, die sich dabei lohnen: Den Schlüssel als Umgebungsvariable anlegen und nicht in jeden Request einzeln, dann kannst du zwischen Test und Produktion umschalten, ohne 20 Aufrufe zu ändern. Die Requests als Sammlung speichern, weil du sie beim nächsten Kunden wieder brauchst. Und wenn ein Aufruf steht, den Code-Schnipsel exportieren, den die meisten Clients für C#, Java und andere Sprachen erzeugen. Der ist ein besserer Startpunkt als ein Beispiel aus einem Forum, weil er genau die Header trägt, mit denen es gerade funktioniert hat.",[11,2201,2202,2203,2206],{},"Und bevor der erste Schreibzugriff läuft: Unter ",[45,2204,2205],{},"api-staging.artesa.dev"," liegt unsere Spielwiese. Dort darf schiefgehen, was schiefgehen will, und niemand im Büro muss danach 200 doppelte Kunden von Hand aufräumen. Der Datenbestand dort ist nicht aktuell, und es können Funktionen darin stecken, die noch nicht veröffentlicht sind.",[95,2208,2210],{"id":2209},"rest-api-aus-vba-aufrufen-excel-und-access","REST API aus VBA aufrufen: Excel und Access",[11,2212,2213,2214,2217,2218,2223,2224,2227],{},"VBA kann HTTP von Hause aus, über ",[45,2215,2216],{},"WinHttp.WinHttpRequest.5.1",". Was fehlt, ist JSON: dafür holst du dir ",[81,2219,2222],{"href":2220,"rel":2221},"https:\u002F\u002Fgithub.com\u002FVBA-tools\u002FVBA-JSON",[85],"VBA-JSON",", ein einzelnes Modul unter MIT-Lizenz, das du als ",[45,2225,2226],{},"JsonConverter.bas"," importierst.",[165,2229,2233],{"className":2230,"code":2231,"language":2232,"meta":170,"style":170},"language-vb shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","Public Function ArtesaGet(ByVal Pfad As String) As Object\n    Dim Http As Object\n    Set Http = CreateObject(\"WinHttp.WinHttpRequest.5.1\")\n\n    Http.Open \"GET\", \"https:\u002F\u002Fapi.artesa.de\" & Pfad, False\n    Http.setRequestHeader \"Authorization\", \"Bearer \" & ApiSchluessel()\n    Http.setRequestHeader \"Accept\", \"application\u002Fjson\"\n    Http.send\n\n    If Http.Status \u003C> 200 Then\n        Err.Raise vbObjectError + 1000, , _\n            \"Artesa API \" & Http.Status & \": \" & Http.responseText\n    End If\n\n    Set ArtesaGet = JsonConverter.ParseJson(Http.responseText)\nEnd Function\n","vb",[45,2234,2235,2265,2277,2302,2308,2337,2364,2383,2388,2392,2409,2426,2455,2460,2464,2486],{"__ignoreMap":170},[174,2236,2237,2240,2244,2247,2250,2253,2256,2259,2262],{"class":176,"line":177},[174,2238,2239],{"class":342},"Public Function ",[174,2241,2243],{"class":2242},"s2Zo4","ArtesaGet",[174,2245,2246],{"class":333},"(",[174,2248,2249],{"class":183},"ByVal Pfad ",[174,2251,2252],{"class":333},"As",[174,2254,2255],{"class":416}," String",[174,2257,2258],{"class":333},")",[174,2260,2261],{"class":333}," As",[174,2263,2264],{"class":416}," Object\n",[174,2266,2267,2270,2273,2275],{"class":176,"line":197},[174,2268,2269],{"class":342},"    Dim",[174,2271,2272],{"class":183}," Http ",[174,2274,2252],{"class":333},[174,2276,2264],{"class":416},[174,2278,2279,2282,2285,2288,2291,2293,2295,2297,2299],{"class":176,"line":211},[174,2280,2281],{"class":342},"    Set ",[174,2283,2284],{"class":183},"Http ",[174,2286,2287],{"class":333},"=",[174,2289,2290],{"class":2242}," CreateObject",[174,2292,2246],{"class":333},[174,2294,346],{"class":333},[174,2296,2216],{"class":207},[174,2298,346],{"class":333},[174,2300,2301],{"class":333},")\n",[174,2303,2304],{"class":176,"line":221},[174,2305,2307],{"emptyLinePlaceholder":2306},true,"\n",[174,2309,2310,2313,2315,2317,2319,2321,2323,2326,2328,2331,2334],{"class":176,"line":389},[174,2311,2312],{"class":183},"    Http.Open ",[174,2314,346],{"class":333},[174,2316,47],{"class":207},[174,2318,346],{"class":333},[174,2320,314],{"class":183},[174,2322,346],{"class":333},[174,2324,2325],{"class":207},"https:\u002F\u002Fapi.artesa.de",[174,2327,346],{"class":333},[174,2329,2330],{"class":333}," &",[174,2332,2333],{"class":183}," Pfad,",[174,2335,2336],{"class":333}," False\n",[174,2338,2339,2342,2344,2346,2348,2350,2352,2354,2356,2358,2361],{"class":176,"line":404},[174,2340,2341],{"class":183},"    Http.setRequestHeader ",[174,2343,346],{"class":333},[174,2345,72],{"class":207},[174,2347,346],{"class":333},[174,2349,314],{"class":183},[174,2351,346],{"class":333},[174,2353,2028],{"class":207},[174,2355,346],{"class":333},[174,2357,2330],{"class":333},[174,2359,2360],{"class":2242}," ApiSchluessel",[174,2362,2363],{"class":333},"()\n",[174,2365,2366,2368,2370,2372,2374,2376,2378,2381],{"class":176,"line":410},[174,2367,2341],{"class":183},[174,2369,346],{"class":333},[174,2371,224],{"class":207},[174,2373,346],{"class":333},[174,2375,314],{"class":183},[174,2377,346],{"class":333},[174,2379,2380],{"class":207},"application\u002Fjson",[174,2382,775],{"class":333},[174,2384,2385],{"class":176,"line":429},[174,2386,2387],{"class":183},"    Http.send\n",[174,2389,2390],{"class":176,"line":451},[174,2391,2307],{"emptyLinePlaceholder":2306},[174,2393,2394,2397,2400,2403,2406],{"class":176,"line":472},[174,2395,2396],{"class":180},"    If",[174,2398,2399],{"class":183}," Http.Status ",[174,2401,2402],{"class":333},"\u003C>",[174,2404,2405],{"class":187}," 200",[174,2407,2408],{"class":180}," Then\n",[174,2410,2411,2414,2417,2420,2423],{"class":176,"line":493},[174,2412,2413],{"class":183},"        Err.Raise ",[174,2415,2416],{"class":416},"vbObjectError",[174,2418,2419],{"class":333}," +",[174,2421,2422],{"class":187}," 1000",[174,2424,2425],{"class":183},", , _\n",[174,2427,2428,2431,2434,2436,2438,2440,2443,2445,2448,2450,2452],{"class":176,"line":514},[174,2429,2430],{"class":333},"            \"",[174,2432,2433],{"class":207},"Artesa API ",[174,2435,346],{"class":333},[174,2437,2330],{"class":333},[174,2439,2399],{"class":183},[174,2441,2442],{"class":333},"&",[174,2444,441],{"class":333},[174,2446,2447],{"class":207},": ",[174,2449,346],{"class":333},[174,2451,2330],{"class":333},[174,2453,2454],{"class":183}," Http.responseText\n",[174,2456,2457],{"class":176,"line":535},[174,2458,2459],{"class":180},"    End If\n",[174,2461,2462],{"class":176,"line":549},[174,2463,2307],{"emptyLinePlaceholder":2306},[174,2465,2466,2468,2471,2473,2476,2479,2481,2484],{"class":176,"line":605},[174,2467,2281],{"class":342},[174,2469,2470],{"class":183},"ArtesaGet ",[174,2472,2287],{"class":333},[174,2474,2475],{"class":183}," JsonConverter.",[174,2477,2478],{"class":2242},"ParseJson",[174,2480,2246],{"class":333},[174,2482,2483],{"class":183},"Http.responseText",[174,2485,2301],{"class":333},[174,2487,2488],{"class":176,"line":611},[174,2489,2490],{"class":342},"End Function\n",[11,2492,2493,2496],{},[45,2494,2495],{},"ApiSchluessel()"," ist dabei eine eigene Funktion, die den Schlüssel aus einer Konfigurationsdatei oder der Registry liest, nicht eine Konstante zwei Zeilen weiter oben. Benutzt wird das Ganze so:",[165,2498,2500],{"className":2230,"code":2499,"language":2232,"meta":170,"style":170},"Dim Antwort As Object, Kunde As Variant\n\nSet Antwort = ArtesaGet(\"\u002Fv1\u002Fcustomers?size=20&page=0\")\n\nFor Each Kunde In Antwort(\"items\")\n    Debug.Print Kunde(\"id\"), Kunde(\"companyName\")\nNext Kunde\n\nDebug.Print \"Seite\"; Antwort(\"page\"); \"von\"; Antwort(\"pages\")\n",[45,2501,2502,2523,2527,2551,2555,2578,2610,2618,2622],{"__ignoreMap":170},[174,2503,2504,2507,2510,2512,2515,2518,2520],{"class":176,"line":177},[174,2505,2506],{"class":342},"Dim",[174,2508,2509],{"class":183}," Antwort ",[174,2511,2252],{"class":333},[174,2513,2514],{"class":416}," Object",[174,2516,2517],{"class":183},", Kunde ",[174,2519,2252],{"class":333},[174,2521,2522],{"class":416}," Variant\n",[174,2524,2525],{"class":176,"line":197},[174,2526,2307],{"emptyLinePlaceholder":2306},[174,2528,2529,2532,2535,2537,2540,2542,2544,2547,2549],{"class":176,"line":211},[174,2530,2531],{"class":342},"Set ",[174,2533,2534],{"class":183},"Antwort ",[174,2536,2287],{"class":333},[174,2538,2539],{"class":2242}," ArtesaGet",[174,2541,2246],{"class":333},[174,2543,346],{"class":333},[174,2545,2546],{"class":207},"\u002Fv1\u002Fcustomers?size=20&page=0",[174,2548,346],{"class":333},[174,2550,2301],{"class":333},[174,2552,2553],{"class":176,"line":221},[174,2554,2307],{"emptyLinePlaceholder":2306},[174,2556,2557,2560,2563,2566,2568,2570,2572,2574,2576],{"class":176,"line":389},[174,2558,2559],{"class":180},"For",[174,2561,2562],{"class":180}," Each",[174,2564,2565],{"class":183}," Kunde In ",[174,2567,1052],{"class":2242},[174,2569,2246],{"class":333},[174,2571,346],{"class":333},[174,2573,394],{"class":207},[174,2575,346],{"class":333},[174,2577,2301],{"class":333},[174,2579,2580,2583,2586,2588,2590,2592,2594,2596,2598,2600,2602,2604,2606,2608],{"class":176,"line":404},[174,2581,2582],{"class":183},"    Debug.Print ",[174,2584,2585],{"class":2242},"Kunde",[174,2587,2246],{"class":333},[174,2589,346],{"class":333},[174,2591,417],{"class":207},[174,2593,346],{"class":333},[174,2595,2258],{"class":333},[174,2597,314],{"class":183},[174,2599,2585],{"class":2242},[174,2601,2246],{"class":333},[174,2603,346],{"class":333},[174,2605,456],{"class":207},[174,2607,346],{"class":333},[174,2609,2301],{"class":333},[174,2611,2612,2615],{"class":176,"line":410},[174,2613,2614],{"class":180},"Next",[174,2616,2617],{"class":183}," Kunde\n",[174,2619,2620],{"class":176,"line":429},[174,2621,2307],{"emptyLinePlaceholder":2306},[174,2623,2624,2627,2629,2632,2634,2637,2639,2641,2643,2645,2647,2649,2651,2653,2656,2658,2660,2662,2664,2666,2668,2670],{"class":176,"line":451},[174,2625,2626],{"class":183},"Debug.Print ",[174,2628,346],{"class":333},[174,2630,2631],{"class":207},"Seite",[174,2633,346],{"class":333},[174,2635,2636],{"class":183},"; ",[174,2638,1052],{"class":2242},[174,2640,2246],{"class":333},[174,2642,346],{"class":333},[174,2644,343],{"class":207},[174,2646,346],{"class":333},[174,2648,2258],{"class":333},[174,2650,2636],{"class":183},[174,2652,346],{"class":333},[174,2654,2655],{"class":207},"von",[174,2657,346],{"class":333},[174,2659,2636],{"class":183},[174,2661,1052],{"class":2242},[174,2663,2246],{"class":333},[174,2665,346],{"class":333},[174,2667,361],{"class":207},[174,2669,346],{"class":333},[174,2671,2301],{"class":333},[11,2673,2674],{},"Drei Stellen, an denen es in VBA typischerweise klemmt:",[119,2676,2677,2700,2723],{"type":868},[870,2678,2680],{"title":2679},"Fehlende Felder werfen keinen Fehler",[11,2681,2682,2684,2685,2688,2689,2692,2693,2695,2696,2699],{},[45,2683,2478],{}," liefert Objekte als ",[45,2686,2687],{},"Dictionary",". Ein Zugriff auf einen Schlüssel, den die Antwort nicht enthält, gibt dir ",[45,2690,2691],{},"Empty"," statt eines Fehlers. Bei optionalen Feldern wie ",[45,2694,477],{}," erst ",[45,2697,2698],{},"Kunde.Exists(\"externalId\")"," fragen.",[870,2701,2703],{"title":2702},"Listen sind Collections, keine Arrays",[11,2704,2705,2708,2709,2712,2713,2716,2717,2719,2720,93],{},[45,2706,2707],{},"Antwort(\"items\")"," ist eine ",[45,2710,2711],{},"Collection",". ",[45,2714,2715],{},"For Each"," funktioniert, ein Index ab ",[45,2718,1245],{}," nicht: gezählt wird ab ",[45,2721,2722],{},"1",[870,2724,2726],{"title":2725},"Body per String zusammenbauen",[11,2727,2728,2729,2731,2732,2735],{},"Für Schreibzugriffe nicht die Anführungszeichen selbst zusammensetzen. Ein ",[45,2730,2687],{}," füllen und mit ",[45,2733,2734],{},"JsonConverter.ConvertToJson"," ausgeben, dann stimmen Kommas und Sonderzeichen von allein.",[11,2737,2738,2739,2742,2743,2746],{},"Umlaute kommen übrigens richtig an: Die API schickt ",[45,2740,2741],{},"charset=utf-8"," mit, und ",[45,2744,2745],{},"responseText"," wertet das aus.",[95,2748,2750],{"id":2749},"rest-api-aus-c-aufrufen-httpclient-und-system-text-json","REST API aus C# aufrufen: HttpClient und System.Text.Json",[11,2752,2753],{},"In .NET ist beides eingebaut, der HTTP-Client und der JSON-Serialisierer:",[165,2755,2759],{"className":2756,"code":2757,"language":2758,"meta":170,"style":170},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","using System.Net.Http.Headers;\nusing System.Net.Http.Json;\nusing System.Text.Json;\n\n\u002F\u002F Eine Instanz für die Lebensdauer der Anwendung, nicht eine pro Aufruf.\nstatic readonly HttpClient Http = new()\n{\n    BaseAddress = new Uri(\"https:\u002F\u002Fapi.artesa.de\u002F\"),\n};\n\nHttp.DefaultRequestHeaders.Authorization =\n    new AuthenticationHeaderValue(\"Bearer\", ApiSchluessel());\n\n\u002F\u002F JsonSerializerDefaults.Web bringt camelCase mit, sonst findet der\n\u002F\u002F Serialisierer companyName nicht.\nvar optionen = new JsonSerializerOptions(JsonSerializerDefaults.Web);\n\nrecord Kunde(int Id, string? CompanyName, string? ExternalId, DateTimeOffset UpdatedAt);\nrecord Seite\u003CT>(int Page, int Pages, int Size, List\u003CT> Items);\n\nvar seite = await Http.GetFromJsonAsync\u003CSeite\u003CKunde>>(\n    \"v1\u002Fcustomers?size=20&page=0\", optionen);\n\nforeach (var kunde in seite!.Items)\n    Console.WriteLine($\"{kunde.Id} {kunde.CompanyName}\");\n","csharp",[45,2760,2761,2787,2808,2825,2829,2835,2855,2859,2884,2889,2893,2910,2933,2937,2942,2947,2975,2979,3023,3074,3078,3108,3123,3127,3153],{"__ignoreMap":170},[174,2762,2763,2766,2769,2771,2774,2776,2779,2781,2784],{"class":176,"line":177},[174,2764,2765],{"class":187},"using",[174,2767,2768],{"class":183}," System",[174,2770,93],{"class":333},[174,2772,2773],{"class":183},"Net",[174,2775,93],{"class":333},[174,2777,2778],{"class":183},"Http",[174,2780,93],{"class":333},[174,2782,2783],{"class":183},"Headers",[174,2785,2786],{"class":333},";\n",[174,2788,2789,2791,2793,2795,2797,2799,2801,2803,2806],{"class":176,"line":197},[174,2790,2765],{"class":187},[174,2792,2768],{"class":183},[174,2794,93],{"class":333},[174,2796,2773],{"class":183},[174,2798,93],{"class":333},[174,2800,2778],{"class":183},[174,2802,93],{"class":333},[174,2804,2805],{"class":183},"Json",[174,2807,2786],{"class":333},[174,2809,2810,2812,2814,2816,2819,2821,2823],{"class":176,"line":211},[174,2811,2765],{"class":187},[174,2813,2768],{"class":183},[174,2815,93],{"class":333},[174,2817,2818],{"class":183},"Text",[174,2820,93],{"class":333},[174,2822,2805],{"class":183},[174,2824,2786],{"class":333},[174,2826,2827],{"class":176,"line":221},[174,2828,2307],{"emptyLinePlaceholder":2306},[174,2830,2831],{"class":176,"line":389},[174,2832,2834],{"class":2833},"sHwdD","\u002F\u002F Eine Instanz für die Lebensdauer der Anwendung, nicht eine pro Aufruf.\n",[174,2836,2837,2840,2843,2846,2849,2852],{"class":176,"line":404},[174,2838,2839],{"class":342},"static",[174,2841,2842],{"class":342}," readonly",[174,2844,2845],{"class":416}," HttpClient",[174,2847,2848],{"class":416}," Http",[174,2850,2851],{"class":333}," =",[174,2853,2854],{"class":333}," new()\n",[174,2856,2857],{"class":176,"line":410},[174,2858,334],{"class":333},[174,2860,2861,2864,2866,2869,2872,2874,2876,2879,2881],{"class":176,"line":429},[174,2862,2863],{"class":183},"    BaseAddress ",[174,2865,2287],{"class":333},[174,2867,2868],{"class":333}," new",[174,2870,2871],{"class":416}," Uri",[174,2873,2246],{"class":333},[174,2875,346],{"class":333},[174,2877,2878],{"class":207},"https:\u002F\u002Fapi.artesa.de\u002F",[174,2880,346],{"class":333},[174,2882,2883],{"class":333},"),\n",[174,2885,2886],{"class":176,"line":451},[174,2887,2888],{"class":333},"};\n",[174,2890,2891],{"class":176,"line":472},[174,2892,2307],{"emptyLinePlaceholder":2306},[174,2894,2895,2897,2899,2902,2904,2907],{"class":176,"line":493},[174,2896,2778],{"class":183},[174,2898,93],{"class":333},[174,2900,2901],{"class":183},"DefaultRequestHeaders",[174,2903,93],{"class":333},[174,2905,2906],{"class":183},"Authorization ",[174,2908,2909],{"class":333},"=\n",[174,2911,2912,2915,2918,2920,2922,2924,2926,2928,2930],{"class":176,"line":514},[174,2913,2914],{"class":333},"    new",[174,2916,2917],{"class":416}," AuthenticationHeaderValue",[174,2919,2246],{"class":333},[174,2921,346],{"class":333},[174,2923,1181],{"class":207},[174,2925,346],{"class":333},[174,2927,571],{"class":333},[174,2929,2360],{"class":2242},[174,2931,2932],{"class":333},"());\n",[174,2934,2935],{"class":176,"line":535},[174,2936,2307],{"emptyLinePlaceholder":2306},[174,2938,2939],{"class":176,"line":549},[174,2940,2941],{"class":2833},"\u002F\u002F JsonSerializerDefaults.Web bringt camelCase mit, sonst findet der\n",[174,2943,2944],{"class":176,"line":605},[174,2945,2946],{"class":2833},"\u002F\u002F Serialisierer companyName nicht.\n",[174,2948,2949,2952,2955,2957,2959,2962,2964,2967,2969,2972],{"class":176,"line":611},[174,2950,2951],{"class":416},"var",[174,2953,2954],{"class":416}," optionen",[174,2956,2851],{"class":333},[174,2958,2868],{"class":333},[174,2960,2961],{"class":416}," JsonSerializerOptions",[174,2963,2246],{"class":333},[174,2965,2966],{"class":183},"JsonSerializerDefaults",[174,2968,93],{"class":333},[174,2970,2971],{"class":183},"Web",[174,2973,2974],{"class":333},");\n",[174,2976,2977],{"class":176,"line":625},[174,2978,2307],{"emptyLinePlaceholder":2306},[174,2980,2981,2984,2987,2990,2993,2995,2998,3001,3004,3006,3008,3010,3013,3015,3018,3021],{"class":176,"line":674},[174,2982,2983],{"class":416},"record",[174,2985,2986],{"class":416}," Kunde",[174,2988,2989],{"class":333},"(int",[174,2991,2992],{"class":416}," Id",[174,2994,571],{"class":333},[174,2996,2997],{"class":333}," string",[174,2999,3000],{"class":333},"?",[174,3002,3003],{"class":416}," CompanyName",[174,3005,571],{"class":333},[174,3007,2997],{"class":333},[174,3009,3000],{"class":333},[174,3011,3012],{"class":416}," ExternalId",[174,3014,571],{"class":333},[174,3016,3017],{"class":416}," DateTimeOffset",[174,3019,3020],{"class":416}," UpdatedAt",[174,3022,2974],{"class":333},[174,3024,3025,3027,3030,3033,3036,3039,3042,3044,3047,3050,3052,3054,3057,3059,3062,3064,3066,3069,3072],{"class":176,"line":679},[174,3026,2983],{"class":416},[174,3028,3029],{"class":416}," Seite",[174,3031,3032],{"class":333},"\u003C",[174,3034,3035],{"class":416},"T",[174,3037,3038],{"class":333},">(int",[174,3040,3041],{"class":416}," Page",[174,3043,571],{"class":333},[174,3045,3046],{"class":333}," int",[174,3048,3049],{"class":416}," Pages",[174,3051,571],{"class":333},[174,3053,3046],{"class":333},[174,3055,3056],{"class":416}," Size",[174,3058,571],{"class":333},[174,3060,3061],{"class":416}," List",[174,3063,3032],{"class":333},[174,3065,3035],{"class":416},[174,3067,3068],{"class":333},">",[174,3070,3071],{"class":416}," Items",[174,3073,2974],{"class":333},[174,3075,3076],{"class":176,"line":694},[174,3077,2307],{"emptyLinePlaceholder":2306},[174,3079,3080,3082,3085,3087,3090,3092,3094,3097,3099,3101,3103,3105],{"class":176,"line":716},[174,3081,2951],{"class":416},[174,3083,3084],{"class":416}," seite",[174,3086,2851],{"class":333},[174,3088,3089],{"class":333}," await",[174,3091,2848],{"class":183},[174,3093,93],{"class":333},[174,3095,3096],{"class":2242},"GetFromJsonAsync",[174,3098,3032],{"class":333},[174,3100,2631],{"class":416},[174,3102,3032],{"class":333},[174,3104,2585],{"class":416},[174,3106,3107],{"class":333},">>(\n",[174,3109,3110,3112,3115,3117,3119,3121],{"class":176,"line":737},[174,3111,1731],{"class":333},[174,3113,3114],{"class":207},"v1\u002Fcustomers?size=20&page=0",[174,3116,346],{"class":333},[174,3118,571],{"class":333},[174,3120,2954],{"class":183},[174,3122,2974],{"class":333},[174,3124,3125],{"class":176,"line":758},[174,3126,2307],{"emptyLinePlaceholder":2306},[174,3128,3129,3132,3135,3137,3140,3143,3145,3148,3151],{"class":176,"line":778},[174,3130,3131],{"class":180},"foreach",[174,3133,3134],{"class":333}," (",[174,3136,2951],{"class":416},[174,3138,3139],{"class":416}," kunde",[174,3141,3142],{"class":180}," in",[174,3144,3084],{"class":183},[174,3146,3147],{"class":333},"!.",[174,3149,3150],{"class":183},"Items",[174,3152,2301],{"class":333},[174,3154,3155,3158,3160,3163,3165,3168,3170,3173,3175,3178,3181,3184,3186,3188,3190,3192,3194],{"class":176,"line":784},[174,3156,3157],{"class":183},"    Console",[174,3159,93],{"class":333},[174,3161,3162],{"class":2242},"WriteLine",[174,3164,2246],{"class":333},[174,3166,3167],{"class":333},"$\"",[174,3169,1262],{"class":333},[174,3171,3172],{"class":183},"kunde",[174,3174,93],{"class":333},[174,3176,3177],{"class":183},"Id",[174,3179,3180],{"class":333},"}",[174,3182,3183],{"class":333}," {",[174,3185,3172],{"class":183},[174,3187,93],{"class":333},[174,3189,945],{"class":183},[174,3191,3180],{"class":333},[174,3193,346],{"class":333},[174,3195,2974],{"class":333},[11,3197,1543,3198,3200,3201,3203],{},[45,3199,55],{}," ist dann eine Zeile, und der anonyme Typ im Body ist genau das, was ",[45,3202,55],{}," will: nur das eine Feld.",[165,3205,3207],{"className":2756,"code":3206,"language":2758,"meta":170,"style":170},"var antwort = await Http.PatchAsJsonAsync(\n    $\"v1\u002Fcustomers\u002F{kunde.Id}\",\n    new { companyName = \"Metallbau Sander GmbH & Co. KG\" },\n    optionen);\n\nantwort.EnsureSuccessStatusCode();\n",[45,3208,3209,3230,3252,3273,3280,3284],{"__ignoreMap":170},[174,3210,3211,3213,3216,3218,3220,3222,3224,3227],{"class":176,"line":177},[174,3212,2951],{"class":416},[174,3214,3215],{"class":416}," antwort",[174,3217,2851],{"class":333},[174,3219,3089],{"class":333},[174,3221,2848],{"class":183},[174,3223,93],{"class":333},[174,3225,3226],{"class":2242},"PatchAsJsonAsync",[174,3228,3229],{"class":333},"(\n",[174,3231,3232,3235,3238,3240,3242,3244,3246,3248,3250],{"class":176,"line":197},[174,3233,3234],{"class":333},"    $\"",[174,3236,3237],{"class":207},"v1\u002Fcustomers\u002F",[174,3239,1262],{"class":333},[174,3241,3172],{"class":183},[174,3243,93],{"class":333},[174,3245,3177],{"class":183},[174,3247,3180],{"class":333},[174,3249,346],{"class":333},[174,3251,354],{"class":333},[174,3253,3254,3256,3258,3261,3263,3265,3268,3270],{"class":176,"line":211},[174,3255,2914],{"class":333},[174,3257,3183],{"class":333},[174,3259,3260],{"class":183}," companyName ",[174,3262,2287],{"class":333},[174,3264,441],{"class":333},[174,3266,3267],{"class":207},"Metallbau Sander GmbH & Co. KG",[174,3269,346],{"class":333},[174,3271,3272],{"class":333}," },\n",[174,3274,3275,3278],{"class":176,"line":221},[174,3276,3277],{"class":183},"    optionen",[174,3279,2974],{"class":333},[174,3281,3282],{"class":176,"line":389},[174,3283,2307],{"emptyLinePlaceholder":2306},[174,3285,3286,3289,3291,3294],{"class":176,"line":404},[174,3287,3288],{"class":183},"antwort",[174,3290,93],{"class":333},[174,3292,3293],{"class":2242},"EnsureSuccessStatusCode",[174,3295,3296],{"class":333},"();\n",[11,3298,3299,3300,3303,3304,3307],{},"Der Fallstrick in .NET ist ein anderer als in VBA: ",[45,3301,3302],{},"new HttpClient()"," pro Aufruf sieht harmlos aus, lässt aber Verbindungen offen und läuft unter Last in die Portknappheit. Eine Instanz für die ganze Anwendung, oder ",[45,3305,3306],{},"IHttpClientFactory",", wenn du sowieso mit Dependency Injection arbeitest.",[95,3309,3311],{"id":3310},"rest-api-aus-java-aufrufen-httpclient-und-jackson","REST API aus Java aufrufen: HttpClient und Jackson",[11,3313,3314],{},"Seit Java 11 steckt der HTTP-Client in der Standardbibliothek, fürs JSON kommt eine Bibliothek dazu, meist Jackson.",[165,3316,3320],{"className":3317,"code":3318,"language":3319,"meta":170,"style":170},"language-java shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","record Kunde(int id, String companyName, String externalId) {}\nrecord Seite\u003CT>(int page, int pages, int size, List\u003CT> items) {}\n\nvar client = HttpClient.newHttpClient();\nvar mapper = new ObjectMapper()\n    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);\n\nvar request = HttpRequest.newBuilder()\n    .uri(URI.create(\"https:\u002F\u002Fapi.artesa.de\u002Fv1\u002Fcustomers?size=20&page=0\"))\n    .header(\"Authorization\", \"Bearer \" + apiSchluessel())\n    .header(\"Accept\", \"application\u002Fjson\")\n    .GET()\n    .build();\n\nvar antwort = client.send(request, HttpResponse.BodyHandlers.ofString());\n\nif (antwort.statusCode() != 200) {\n    throw new IOException(\"Artesa API \" + antwort.statusCode() + \": \" + antwort.body());\n}\n\nvar seite = mapper.readValue(antwort.body(), new TypeReference\u003CSeite\u003CKunde>>() {});\n\nfor (var kunde : seite.items()) {\n    System.out.println(kunde.id() + \" \" + kunde.companyName());\n}\n","java",[45,3321,3322,3355,3404,3408,3426,3442,3465,3469,3488,3517,3548,3572,3580,3589,3593,3632,3636,3662,3709,3713,3717,3764,3768,3793,3834],{"__ignoreMap":170},[174,3323,3324,3326,3328,3330,3333,3336,3338,3340,3343,3345,3347,3350,3352],{"class":176,"line":177},[174,3325,2983],{"class":342},[174,3327,2986],{"class":416},[174,3329,2246],{"class":333},[174,3331,3332],{"class":342},"int",[174,3334,3335],{"class":183}," id",[174,3337,571],{"class":333},[174,3339,2255],{"class":342},[174,3341,3342],{"class":183}," companyName",[174,3344,571],{"class":333},[174,3346,2255],{"class":342},[174,3348,3349],{"class":183}," externalId",[174,3351,2258],{"class":333},[174,3353,3354],{"class":333}," {}\n",[174,3356,3357,3359,3361,3363,3365,3368,3370,3373,3375,3377,3380,3382,3384,3387,3389,3391,3393,3395,3397,3400,3402],{"class":176,"line":197},[174,3358,2983],{"class":342},[174,3360,3029],{"class":416},[174,3362,3032],{"class":333},[174,3364,3035],{"class":342},[174,3366,3367],{"class":333},">(",[174,3369,3332],{"class":342},[174,3371,3372],{"class":183}," page",[174,3374,571],{"class":333},[174,3376,3046],{"class":342},[174,3378,3379],{"class":183}," pages",[174,3381,571],{"class":333},[174,3383,3046],{"class":342},[174,3385,3386],{"class":183}," size",[174,3388,571],{"class":333},[174,3390,3061],{"class":342},[174,3392,3032],{"class":333},[174,3394,3035],{"class":183},[174,3396,3068],{"class":333},[174,3398,3399],{"class":183}," items",[174,3401,2258],{"class":333},[174,3403,3354],{"class":333},[174,3405,3406],{"class":176,"line":211},[174,3407,2307],{"emptyLinePlaceholder":2306},[174,3409,3410,3412,3415,3417,3419,3421,3424],{"class":176,"line":221},[174,3411,2951],{"class":342},[174,3413,3414],{"class":183}," client ",[174,3416,2287],{"class":333},[174,3418,2845],{"class":183},[174,3420,93],{"class":333},[174,3422,3423],{"class":2242},"newHttpClient",[174,3425,3296],{"class":333},[174,3427,3428,3430,3433,3435,3437,3440],{"class":176,"line":389},[174,3429,2951],{"class":342},[174,3431,3432],{"class":183}," mapper ",[174,3434,2287],{"class":333},[174,3436,2868],{"class":180},[174,3438,3439],{"class":2242}," ObjectMapper",[174,3441,2363],{"class":333},[174,3443,3444,3447,3450,3452,3455,3457,3460,3462],{"class":176,"line":404},[174,3445,3446],{"class":333},"    .",[174,3448,3449],{"class":2242},"configure",[174,3451,2246],{"class":333},[174,3453,3454],{"class":183},"DeserializationFeature",[174,3456,93],{"class":333},[174,3458,3459],{"class":183},"FAIL_ON_UNKNOWN_PROPERTIES",[174,3461,571],{"class":333},[174,3463,3464],{"class":333}," false);\n",[174,3466,3467],{"class":176,"line":410},[174,3468,2307],{"emptyLinePlaceholder":2306},[174,3470,3471,3473,3476,3478,3481,3483,3486],{"class":176,"line":429},[174,3472,2951],{"class":342},[174,3474,3475],{"class":183}," request ",[174,3477,2287],{"class":333},[174,3479,3480],{"class":183}," HttpRequest",[174,3482,93],{"class":333},[174,3484,3485],{"class":2242},"newBuilder",[174,3487,2363],{"class":333},[174,3489,3490,3492,3495,3497,3500,3502,3505,3507,3509,3512,3514],{"class":176,"line":451},[174,3491,3446],{"class":333},[174,3493,3494],{"class":2242},"uri",[174,3496,2246],{"class":333},[174,3498,3499],{"class":183},"URI",[174,3501,93],{"class":333},[174,3503,3504],{"class":2242},"create",[174,3506,2246],{"class":333},[174,3508,346],{"class":333},[174,3510,3511],{"class":207},"https:\u002F\u002Fapi.artesa.de\u002Fv1\u002Fcustomers?size=20&page=0",[174,3513,346],{"class":333},[174,3515,3516],{"class":333},"))\n",[174,3518,3519,3521,3524,3526,3528,3530,3532,3534,3536,3538,3540,3542,3545],{"class":176,"line":472},[174,3520,3446],{"class":333},[174,3522,3523],{"class":2242},"header",[174,3525,2246],{"class":333},[174,3527,346],{"class":333},[174,3529,72],{"class":207},[174,3531,346],{"class":333},[174,3533,571],{"class":333},[174,3535,441],{"class":333},[174,3537,2028],{"class":207},[174,3539,346],{"class":333},[174,3541,2419],{"class":333},[174,3543,3544],{"class":2242}," apiSchluessel",[174,3546,3547],{"class":333},"())\n",[174,3549,3550,3552,3554,3556,3558,3560,3562,3564,3566,3568,3570],{"class":176,"line":493},[174,3551,3446],{"class":333},[174,3553,3523],{"class":2242},[174,3555,2246],{"class":333},[174,3557,346],{"class":333},[174,3559,224],{"class":207},[174,3561,346],{"class":333},[174,3563,571],{"class":333},[174,3565,441],{"class":333},[174,3567,2380],{"class":207},[174,3569,346],{"class":333},[174,3571,2301],{"class":333},[174,3573,3574,3576,3578],{"class":176,"line":514},[174,3575,3446],{"class":333},[174,3577,47],{"class":2242},[174,3579,2363],{"class":333},[174,3581,3582,3584,3587],{"class":176,"line":535},[174,3583,3446],{"class":333},[174,3585,3586],{"class":2242},"build",[174,3588,3296],{"class":333},[174,3590,3591],{"class":176,"line":549},[174,3592,2307],{"emptyLinePlaceholder":2306},[174,3594,3595,3597,3600,3602,3605,3607,3610,3612,3615,3617,3620,3622,3625,3627,3630],{"class":176,"line":605},[174,3596,2951],{"class":342},[174,3598,3599],{"class":183}," antwort ",[174,3601,2287],{"class":333},[174,3603,3604],{"class":183}," client",[174,3606,93],{"class":333},[174,3608,3609],{"class":2242},"send",[174,3611,2246],{"class":333},[174,3613,3614],{"class":183},"request",[174,3616,571],{"class":333},[174,3618,3619],{"class":183}," HttpResponse",[174,3621,93],{"class":333},[174,3623,3624],{"class":183},"BodyHandlers",[174,3626,93],{"class":333},[174,3628,3629],{"class":2242},"ofString",[174,3631,2932],{"class":333},[174,3633,3634],{"class":176,"line":611},[174,3635,2307],{"emptyLinePlaceholder":2306},[174,3637,3638,3641,3643,3645,3647,3650,3653,3656,3658,3660],{"class":176,"line":625},[174,3639,3640],{"class":180},"if",[174,3642,3134],{"class":333},[174,3644,3288],{"class":183},[174,3646,93],{"class":333},[174,3648,3649],{"class":2242},"statusCode",[174,3651,3652],{"class":333},"()",[174,3654,3655],{"class":333}," !=",[174,3657,2405],{"class":187},[174,3659,2258],{"class":333},[174,3661,691],{"class":333},[174,3663,3664,3667,3669,3672,3674,3676,3678,3680,3682,3684,3686,3688,3690,3692,3694,3696,3698,3700,3702,3704,3707],{"class":176,"line":674},[174,3665,3666],{"class":180},"    throw",[174,3668,2868],{"class":180},[174,3670,3671],{"class":2242}," IOException",[174,3673,2246],{"class":333},[174,3675,346],{"class":333},[174,3677,2433],{"class":207},[174,3679,346],{"class":333},[174,3681,2419],{"class":333},[174,3683,3215],{"class":183},[174,3685,93],{"class":333},[174,3687,3649],{"class":2242},[174,3689,3652],{"class":333},[174,3691,2419],{"class":333},[174,3693,441],{"class":333},[174,3695,2447],{"class":207},[174,3697,346],{"class":333},[174,3699,2419],{"class":333},[174,3701,3215],{"class":183},[174,3703,93],{"class":333},[174,3705,3706],{"class":2242},"body",[174,3708,2932],{"class":333},[174,3710,3711],{"class":176,"line":679},[174,3712,839],{"class":333},[174,3714,3715],{"class":176,"line":694},[174,3716,2307],{"emptyLinePlaceholder":2306},[174,3718,3719,3721,3724,3726,3729,3731,3734,3736,3738,3740,3742,3745,3747,3750,3752,3754,3756,3758,3761],{"class":176,"line":716},[174,3720,2951],{"class":342},[174,3722,3723],{"class":183}," seite ",[174,3725,2287],{"class":333},[174,3727,3728],{"class":183}," mapper",[174,3730,93],{"class":333},[174,3732,3733],{"class":2242},"readValue",[174,3735,2246],{"class":333},[174,3737,3288],{"class":183},[174,3739,93],{"class":333},[174,3741,3706],{"class":2242},[174,3743,3744],{"class":333},"(),",[174,3746,2868],{"class":180},[174,3748,3749],{"class":342}," TypeReference",[174,3751,3032],{"class":333},[174,3753,2631],{"class":342},[174,3755,3032],{"class":333},[174,3757,2585],{"class":342},[174,3759,3760],{"class":333},">>()",[174,3762,3763],{"class":333}," {});\n",[174,3765,3766],{"class":176,"line":737},[174,3767,2307],{"emptyLinePlaceholder":2306},[174,3769,3770,3773,3775,3777,3780,3782,3784,3786,3788,3791],{"class":176,"line":758},[174,3771,3772],{"class":180},"for",[174,3774,3134],{"class":333},[174,3776,2951],{"class":342},[174,3778,3779],{"class":183}," kunde ",[174,3781,204],{"class":180},[174,3783,3084],{"class":183},[174,3785,93],{"class":333},[174,3787,394],{"class":2242},[174,3789,3790],{"class":333},"())",[174,3792,691],{"class":333},[174,3794,3795,3798,3800,3803,3805,3808,3810,3812,3814,3816,3818,3820,3822,3824,3826,3828,3830,3832],{"class":176,"line":778},[174,3796,3797],{"class":183},"    System",[174,3799,93],{"class":333},[174,3801,3802],{"class":183},"out",[174,3804,93],{"class":333},[174,3806,3807],{"class":2242},"println",[174,3809,2246],{"class":333},[174,3811,3172],{"class":183},[174,3813,93],{"class":333},[174,3815,417],{"class":2242},[174,3817,3652],{"class":333},[174,3819,2419],{"class":333},[174,3821,441],{"class":333},[174,3823,441],{"class":333},[174,3825,2419],{"class":333},[174,3827,3139],{"class":183},[174,3829,93],{"class":333},[174,3831,456],{"class":2242},[174,3833,2932],{"class":333},[174,3835,3836],{"class":176,"line":784},[174,3837,839],{"class":333},[11,3839,3840,3841,3843,3844,3846,3847,3850,3851,3853],{},"Die eine Zeile, die hier über die Haltbarkeit deiner Anbindung entscheidet, ist ",[45,3842,3459],{},". Jackson wirft standardmäßig eine Exception, sobald die Antwort ein Feld enthält, das dein Record nicht kennt. Kommt in ",[45,3845,2178],{}," ein Feld hinzu, und das ist eine abwärtskompatible Änderung, für die es kein ",[45,3848,3849],{},"v2"," gibt, steht deine Anbindung. ",[45,3852,989],{}," in .NET ignoriert unbekannte Felder von sich aus, Jackson muss man es sagen.",[95,3855,3857],{"id":3856},"checkliste-vor-dem-produktivbetrieb","Checkliste vor dem Produktivbetrieb",[119,3859,3860,3869,3878,3888,3900,3912,3918],{},[870,3861,3863],{"title":3862},"Gegen Staging getestet",[11,3864,3865,3866,3868],{},"Schreibzugriffe erst gegen ",[45,3867,2205],{},", nicht gegen die Daten, mit denen morgen geplant wird.",[870,3870,3872],{"title":3871},"Delta statt Vollsync",[11,3873,3874,3877],{},[45,3875,3876],{},"updatedAt[$gt]"," mit gemerktem Zeitstempel, ein paar Minuten Überlappung. Alles andere skaliert nicht und produziert nur Last.",[870,3879,3881],{"title":3880},"Schreibzugriffe wiederholbar",[11,3882,3883,3885,3886,93],{},[45,3884,477],{}," gesetzt, Suchen-dann-Anlegen-oder-Ändern statt blindes ",[45,3887,51],{},[870,3889,3891],{"title":3890},"Statuscode vor dem Parsen geprüft",[11,3892,3893,3894,3896,3897,3899],{},"Und ",[45,3895,45],{}," plus ",[45,3898,1931],{}," im Log, mit Zeitstempel und Endpunkt.",[870,3901,3903],{"title":3902},"Wiederholung mit steigendem Abstand",[11,3904,3905,3906,3908,3909,3911],{},"Bei ",[45,3907,2052],{}," warten und erneut versuchen, bei ",[45,3910,2004],{}," nicht. Eine Schleife ohne Wartezeit hilft niemandem.",[870,3913,3915],{"title":3914},"Alles in UTC gerechnet",[11,3916,3917],{},"Umrechnung erst bei der Anzeige. Sommerzeit ist der Grund, warum eine Anbindung im März plötzlich eine Stunde daneben liegt.",[870,3919,3921],{"title":3920},"Version im Pfad, Changelog im Blick",[11,3922,3923,3925,3926,3928,3929,3931],{},[45,3924,2178],{}," bleibt ",[45,3927,2178],{},". Kommt eine Änderung, die bricht, heißt sie ",[45,3930,3849],{}," und du bekommst Bescheid.",[11,3933,3934],{},"Damit ist der Umstieg beschrieben. Es bleibt bei vier Bausteinen pro Aufruf, einem Datenformat mit zwei Klammerarten und einer Handvoll Regeln, die dir bei der nächsten Schnittstelle genauso begegnen.",[2181,3936],{},[3938,3939,3940,3957,3971,3977,3983,4002,4019,4034,4052],"faq-inline",{},[3941,3942,3944],"collapse-item",{"question":3943},"Wie komme ich an einen API-Schlüssel für Artesa?",[11,3945,3946,3947,3952,3953,3956],{},"Auf Anfrage bei uns. Nötig ist ein aktiver Artesa-Zugang des Betriebs, dann stellen wir den Schlüssel bereit, dazu die technische Dokumentation unter ",[81,3948,3951],{"href":3949,"rel":3950},"https:\u002F\u002Fapi.artesa.de\u002Fdocs\u002F",[85],"api.artesa.de\u002Fdocs",". Womit die ",[81,3954,20],{"href":3955},"\u002Fschnittstellen\u002Frest-api"," sonst noch verbunden wird, zeigen die bestehenden Anbindungen.",[3941,3958,3960],{"question":3959},"Gibt es für die Artesa API eine OpenAPI-Spezifikation?",[11,3961,3962,3963,3966,3967,3970],{},"Ja, nach OpenAPI 3.1 und je Ressource abrufbar unter ",[45,3964,3965],{},"\u002Fv1\u002F\u003Cressource>\u002Fspec",", zum Beispiel ",[45,3968,3969],{},"https:\u002F\u002Fapi.artesa.de\u002Fv1\u002Fcustomers\u002Fspec",". Dafür ist kein Schlüssel nötig. Damit lässt sich die Sammlung in Postman importieren oder ein typisierter Client generieren, etwa mit NSwag für .NET oder dem OpenAPI Generator für Java.",[3941,3972,3974],{"question":3973},"Warum JSON und nicht XML?",[11,3975,3976],{},"JSON leistet dasselbe wie XML, mit weniger Aufwand beim Lesen und Schreiben: keine schließenden Tags, keine Unterscheidung zwischen Attribut und Element, keine Namespaces und kein Schema, das man zum Auslesen eines Wertes braucht. Dazu ist es bei gleichem Inhalt kürzer und lässt sich direkt auf Wörterbuch und Liste abbilden. Die Artesa-API antwortet ausschließlich in JSON.",[3941,3978,3980],{"question":3979},"Was ist der Unterschied zwischen JSON und CSV?",[11,3981,3982],{},"CSV ist flach, JSON ist verschachtelt und typisiert. Eine CSV-Zeile hat feste Spalten und kennt nur Text, in JSON kann ein Kunde mehrere Telefonnummern als Liste und die Adresse als eigenes Objekt tragen, und eine Zahl ist als Zahl von einem Text unterscheidbar. Deshalb braucht JSON kein Trennzeichen, keine Spaltenreihenfolge und keine Absprache über die Kodierung.",[3941,3984,3986],{"question":3985},"Kann ich eine REST API direkt aus Excel aufrufen?",[11,3987,3988,3989,3991,3992,3996,3997,4001],{},"Ja. VBA bringt mit ",[45,3990,2216],{}," alles mit, was für den Request nötig ist, für das Parsen der Antwort kommt VBA-JSON dazu. Rein lesend geht es auch ohne eine Zeile Code über Power Query. Wo Excel als Datenquelle sinnvoll bleibt und wo nicht, zeigen wir im Blog ",[81,3993,3995],{"href":3994},"\u002Fblog\u002Fexcel-im-handwerk","„Warum Excel im Handwerk heute nicht mehr funktioniert\"","; über die ",[81,3998,4000],{"href":3999},"\u002Fschnittstellen\u002Fexcel","Excel-Anbindung"," wandern Listen auch ohne eigenen Code hin und zurück.",[3941,4003,4005],{"question":4004},"Wann lohnt sich eigener Code, wann reicht ein Tool wie n8n?",[11,4006,4007,4008,4010,4011,4013,4014,4018],{},"Eigener Code lohnt sich, sobald die Daten aus einem System kommen, an das nur du herankommst, oder die Zuordnung Logik braucht: Abgleich über ",[45,4009,477],{},", Sonderfälle pro Kunde, Umrechnungen. Sollen dagegen zwei Cloud-Systeme schlicht Daten austauschen, ist ",[81,4012,136],{"href":135}," schneller fertig und lässt sich leichter übergeben. Für die Buchhaltung gibt es fertige Wege wie ",[81,4015,4017],{"href":4016},"\u002Fschnittstellen\u002Flexware-office","Lexware Office",", da lohnt kein Eigenbau.",[3941,4020,4022],{"question":4021},"Welche Daten aus einem Handwerksbetrieb kann ich über die Schnittstelle abrufen?",[11,4023,4024,4025,4029,4030,93],{},"Über die offene Schnittstelle von Artesa: Kunden, Aufträge, Arbeitsschritte und Projekte, dazu Benutzer, Zeiteinträge, Abwesenheiten und die Stundenzettel als Summen pro Tag, Woche und Monat samt Genehmigungsstatus. Lesen und schreiben geht in beide Richtungen, jeweils über dieselben vier Methoden. Wo diese Daten im Betrieb entstehen, siehst du an der ",[81,4026,4028],{"href":4027},"\u002Fzeiterfassung","Zeiterfassung",", und welche Systeme heute schon angebunden sind, an den ",[81,4031,4033],{"href":4032},"\u002Fschnittstellen","Schnittstellen",[3941,4035,4037],{"question":4036},"Welche Daten muss der Betrieb in Artesa gepflegt haben, damit die Anbindung läuft?",[11,4038,4039,4040,4042,4043,4047,4048,93],{},"Die Typen, auf die du beim Schreiben verweist: Auftragstypen, Arbeitsschritttypen, Auftragsstatus, Benutzerrollen und Zeiterfassungsarten. Die werden im Betrieb in den Einstellungen angelegt, du liest ihre ",[45,4041,417],{}," über die Settings-Endpunkte und schreibst sie nicht fest in deinen Code. Wie der Betrieb damit arbeitet, steuert er in der ",[81,4044,4046],{"href":4045},"\u002Fauftragsverwaltung","Auftragsverwaltung"," und der ",[81,4049,4051],{"href":4050},"\u002Fmitarbeiterplanung","Mitarbeiterplanung",[3941,4053,4055],{"question":4054},"Gibt es Förderung für die Digitalisierung im Handwerk?",[11,4056,4057,4058,93],{},"Ja, je nach Bundesland und Vorhaben gibt es Zuschüsse, die auch Software und Einführung abdecken. Welche Programme aktuell laufen und was sie jeweils verlangen, steht in der Übersicht ",[81,4059,4061],{"href":4060},"\u002Fblog\u002Ffoerderprogramme","„Förderprogramme für die Digitalisierung im Handwerk\"",[4063,4064,4065],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":170,"searchDepth":197,"depth":197,"links":4067},[4068,4069,4070,4071,4072,4073,4074,4075,4076,4077,4078,4079,4080,4081,4082],{"id":97,"depth":197,"text":98},{"id":159,"depth":197,"text":160},{"id":305,"depth":197,"text":306},{"id":1029,"depth":197,"text":1030},{"id":1152,"depth":197,"text":1153},{"id":1235,"depth":197,"text":1236},{"id":1539,"depth":197,"text":1540},{"id":1891,"depth":197,"text":1892},{"id":2069,"depth":197,"text":2070},{"id":2114,"depth":197,"text":2115},{"id":2185,"depth":197,"text":2186},{"id":2209,"depth":197,"text":2210},{"id":2749,"depth":197,"text":2750},{"id":3310,"depth":197,"text":3311},{"id":3856,"depth":197,"text":3857},"Schnittstellen und IT",{"title":4085,"sub":4086},"Sag uns, welche Richtung du brauchst.","Stamm- und Auftragsdaten hin, Arbeitszeiten zurück: das sind die zwei Richtungen fast jeder Anbindung. Erzähl uns in einer Viertelstunde am Telefon, welches System auf der anderen Seite steht, dann sagen wir dir, was v1 heute abdeckt und ob sich für deinen Fall ein eigener Endpunkt lohnt.","Wie ein HTTP-Request aufgebaut ist, wie du JSON liest, wo der API-Schlüssel hingehört und wie du aus VBA, C# oder Java an die Daten kommst.",false,"md","REST API und JSON: der Einstieg, wenn du aus der Dateiwelt kommst","tabler:braces","\u002Fimages\u002Fblog\u002Frest-api-json-einstieg.webp","Gemalter Umschlag auf einer Werkbank, außen ein Adressfeld und ein Messingschlüssel am Anhänger, innen ein strukturiertes Blatt, Sinnbild für Header und Body eines HTTP-Requests",{},"\u002Fblog\u002F260902-rest-api-json-einstieg","2026-09-02","index, follow",{"title":4099,"description":4100},"REST API und JSON: Einstieg für CSV- und VBA-Umsteiger","Wie ein Request aufgebaut ist, wie du JSON liest, wo der Bearer Token hingehört und wie du aus VBA, C# oder Java an die Daten deiner Handwerkersoftware kommst.","Der Einstieg für Umsteiger von CSV","REST API und JSON","rest-api-json-einstieg",{"title":4105,"subtitle":4106,"shot":4092,"caption":4107},"CSV kannst du. JSON und REST sind neu.","Vier Bausteine, ein Datenformat, und der erste Aufruf aus VBA, C# oder Java.","Aus der Dateiwelt in die Cloud: Wer ein ERP, eine Access-Anwendung oder gewachsene VBA-Makros betreut, hat Importe und Exporte hundertmal gebaut. HTTP und JSON sind trotzdem neu.\n\n▸ Ein Request besteht aus Methode, URL, Header und Body\n▸ JSON ist verschachtelt und typisiert, das ist der Unterschied zu CSV\n▸ Der Schlüssel gehört in den Header, nie in die URL\n▸ Erst im API-Client testen, dann Code schreiben\n\nWer HTTP und JSON einmal gebaut hat, baut jede weitere Anbindung in einem Bruchteil der Zeit.\n\nDen ganzen Artikel über den Link in unserer Bio.\n\n#handwerk #handwerkersoftware #schnittstellen #restapi #digitalisierunghandwerk\n","blog\u002F260902-rest-api-json-einstieg","\u003Cp>Für alle, die aus ERP, Access oder VBA kommen und mit CSV alles gebaut haben, was gebraucht wurde: was eine REST API ist, wie JSON aufgebaut ist, wo der Schlüssel hingehört und wie der erste Aufruf aus VBA, C# oder Java aussieht.\u003C\u002Fp>\n",[4033,4111,4112],"Digitalisierung","Excel",null,"Got5SLFCsHacw8ZJRCY-Im9_jLWXteNkrkzW7dgSKOU",{"id":4116,"draft":4088,"email":4117,"extension":4118,"firstName":4119,"image":4120,"imageAlt":4113,"lastName":4121,"meta":4122,"phone":4123,"role":4126,"stem":4127,"vcf":4128,"__hash__":4129},"employees\u002Femployees\u002Ffrederik.yaml","frederik.schmatz@artesa.de","yaml","Frederik","\u002Fimages\u002Fteam\u002Ffrs.webp","Schmatz",{},{"office":4124,"mobile":4125},"+49 381 260 558 52","+49 176 16814750","Leiter Entwicklung & Infrastruktur","employees\u002Ffrederik","\u002Fvcf\u002Ffrederikschmatz.vcf","H-S7RqtOPQznZLv6zUb88-_iEqUB-0mBcF3TxyWWQcM",[4131,4142,4151,4163],{"slug":4132,"stem":4133,"path":4134,"category":4083,"draft":4088,"headline":4135,"image":4136,"imageAlt":4137,"summary":4138,"tags":4139,"publishDate":4141,"updatedAt":4113},"cloud-oder-on-premise","blog\u002F260811-cloud-oder-on-premise","\u002Fblog\u002F260811-cloud-oder-on-premise","Cloud oder eigener Server: Wo die Daten deines Betriebs liegen sollten","\u002Fimages\u002Fblog\u002Fcloud-oder-on-premise.webp","Gemalte Illustration: links ein Serverschrank im dunklen Abstellraum hinter Eimer und Farbdosen, rechts ein offener Werkzeugkoffer auf der Ladeklappe im Tageslicht","Wo die Daten liegen, wer sie sichert und was die DSGVO damit zu tun hat.\n",[4140,4111,4033],"Softwareauswahl","2026-08-11",{"slug":4143,"stem":4144,"path":4145,"category":4083,"draft":4088,"headline":4146,"image":4147,"imageAlt":4113,"summary":4148,"tags":4149,"publishDate":4150,"updatedAt":4141},"software-schnittstellen","blog\u002F240202-software-schnittstellen","\u002Fblog\u002F240202-software-schnittstellen","Software-Schnittstellen: Was sie sind und wozu du sie brauchst","\u002Fblog\u002F240202-software-schnittstellen-api.webp","Sobald es um Digitalisierung im Handwerk geht, fällt der Begriff Software-Schnittstelle. Hier steht, was damit gemeint ist, welche Arten es gibt und woran du merkst, ob du überhaupt eine brauchst.\n",[4033,4111],"2024-02-02",{"slug":4152,"stem":4153,"path":4154,"category":4155,"draft":4088,"headline":4156,"image":4157,"imageAlt":4158,"summary":4159,"tags":4160,"publishDate":4162,"updatedAt":4113},"trello-asana-teams-handwerk","blog\u002F260828-trello-asana-teams-handwerk","\u002Fblog\u002F260828-trello-asana-teams-handwerk","Behelfslösungen","Trello, Asana und MS Teams im Handwerk: gut für Aufgaben, blind für Kapazität","\u002Fimages\u002Fblog\u002Ftrello-asana-teams-handwerk.webp","Gemalte Illustration: ein Karteikartenkasten und ein Bürostuhl stehen auf einem Baugerüst, daneben ein Monteur mit Akkuschrauber","\u003Cp>Boards ordnen Aufgaben, die Handwerksplanung ordnet Menschen über Zeit. Warum Trello, Asana und Teams an der Kapazitätsachse aufhören und wofür sie im Betrieb weiter taugen.\u003C\u002Fp>\n",[4140,4161,4111],"Auftragsplanung","2026-08-28",{"slug":4164,"stem":4165,"path":4166,"category":4155,"draft":4088,"headline":4167,"image":4168,"imageAlt":4169,"summary":4170,"tags":4171,"publishDate":4175,"updatedAt":4113},"whatsapp-im-handwerk","blog\u002F260826-whatsapp-im-handwerk","\u002Fblog\u002F260826-whatsapp-im-handwerk","WhatsApp im Betrieb: schnell verschickt, später nicht auffindbar","\u002Fimages\u002Fblog\u002Fwhatsapp-im-handwerk.webp","Gemalte Illustration: aus drei privaten Handys fallen Baustellenfotos in einen Strom, der sie fortträgt, während eine Hand ins Leere greift","\u003Cp>WhatsApp ist schnell im Senden und schwach im Wiederfinden. Warum Baustellenfotos auf privaten Handys liegen bleiben, was das bei einer Reklamation kostet und was davon am Auftrag bleiben sollte.\u003C\u002Fp>\n",[4172,4173,4174],"Dokumentation","Kundenkommunikation","Baustelle","2026-08-26",{"id":4177,"title":4178,"active":2306,"body":4179,"color":117,"description":170,"extension":4089,"meta":4186,"navigation":2306,"pages":4187,"path":4188,"seo":4189,"stem":4190,"__hash__":4191},"bannerContent\u002Fbanner.md","Banner",{"type":8,"value":4180,"toc":4184},[4181],[4182,4183],"next-webinar-banner",{},{"title":170,"searchDepth":197,"depth":197,"links":4185},[],{},{},"\u002Fbanner",{"title":4178,"description":170},"banner","x5aPzpKRkSBoonYwBIvjv914W3tuX_RxPOqfH16SJco",[4193,4194,4195,4196,4199],{"title":4090,"slug":4103},{"title":4156,"slug":4152},{"title":4167,"slug":4164},{"title":4197,"slug":4198},"Digitale oder analoge Plantafel? Was die Magnettafel kann und wo sie aufhört","plantafel-digital-oder-analog",{"title":4200,"slug":4201},"Mitarbeiter mit Outlook planen: wo der Kalender aufhört","mitarbeiterplanung-mit-outlook",[4203,4215,4232,4243,4254,4265,4276,4287,4298,4309],{"id":4204,"title":4205,"callToAction":4113,"category":4206,"description":4207,"draft":4088,"end":4113,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4208,"meta":4210,"organizer":4113,"start":4211,"stem":4212,"url":4213,"__hash__":4214},"events\u002Fevents\u002Fwebinar-digitale-planung-2026.yaml","Webinar: Digitale Planung mit Artesa","Webinar","Im praxisnahen Live-Einblick erfährst du als Artesa-Neuling alles wichtige zur Software und wie du damit arbeitest.",{"name":4209},"Online via Teams",{},"2026-01-27","events\u002Fwebinar-digitale-planung-2026","https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002F3619355f-0a41-4b0b-acec-a562c7b9e0c3@2865933d-64a6-4c0b-8170-1f161587b1df","A6Uo_KgvsXZtqRZEV2brZC9CxN5NDs449mNFHGbrKUo",{"id":4216,"title":4217,"callToAction":4218,"category":4206,"description":4224,"draft":4088,"end":4225,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4226,"meta":4228,"organizer":4113,"start":4229,"stem":4230,"url":4113,"__hash__":4231},"events\u002Fevents\u002Fwebinar-live-2026-05-12.yaml","Artesa Live-Webinar",[4219],{"text":4220,"url":4221,"icon":4222,"target":4223},"Jetzt anmelden","https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002FREPLACE_ME_2026-05-12","tabler:brand-teams","_blank","30 Minuten praxisnah und hands-on: Wir zeigen dir live, wie du mit Artesa arbeitest, und beantworten deine Fragen – egal ob du Artesa gerade kennenlernst, in der Demo steckst oder mitten in der Einrichtung bist.","2026-05-12T15:30:00+02:00",{"name":4227},"Online via Microsoft Teams",{},"2026-05-12T15:00:00+02:00","events\u002Fwebinar-live-2026-05-12","drsvIQVStd-obdJhQ3sQv4Rq3AsR-k7ZFCKPQyiQEMA",{"id":4233,"title":4217,"callToAction":4234,"category":4206,"description":4224,"draft":4088,"end":4237,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4238,"meta":4239,"organizer":4113,"start":4240,"stem":4241,"url":4113,"__hash__":4242},"events\u002Fevents\u002Fwebinar-live-2026-05-26.yaml",[4235],{"text":4220,"url":4236,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002FREPLACE_ME_2026-05-26","2026-05-26T15:30:00+02:00",{"name":4227},{},"2026-05-26T15:00:00+02:00","events\u002Fwebinar-live-2026-05-26","rdQgcSZBpA7svI7zkttUg9ZH1w2k5qskMoQ78lsDBLo",{"id":4244,"title":4217,"callToAction":4245,"category":4206,"description":4224,"draft":4088,"end":4248,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4249,"meta":4250,"organizer":4113,"start":4251,"stem":4252,"url":4113,"__hash__":4253},"events\u002Fevents\u002Fwebinar-live-2026-07-21.yaml",[4246],{"text":4220,"url":4247,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002F8b10f62c-59db-42dd-86f4-17e8a6a29f18@2865933d-64a6-4c0b-8170-1f161587b1df","2026-07-21T15:30:00+02:00",{"name":4227},{},"2026-07-21T15:00:00+02:00","events\u002Fwebinar-live-2026-07-21","krer4ljZVnECFwLuTU6OcYa-582fUbRj0aYI_JF1Gnc",{"id":4255,"title":4217,"callToAction":4256,"category":4206,"description":4224,"draft":4088,"end":4259,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4260,"meta":4261,"organizer":4113,"start":4262,"stem":4263,"url":4113,"__hash__":4264},"events\u002Fevents\u002Fwebinar-live-2026-08-04.yaml",[4257],{"text":4220,"url":4258,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002F85911b31-6c2d-4da1-affa-d52b9f348819@2865933d-64a6-4c0b-8170-1f161587b1df","2026-08-04T15:30:00+02:00",{"name":4227},{},"2026-08-04T15:00:00+02:00","events\u002Fwebinar-live-2026-08-04","-VMZWG9th8sZ3hSOjgDv54QWZ6Qa81pN7Dk0E9Qul8M",{"id":4266,"title":4217,"callToAction":4267,"category":4206,"description":4224,"draft":4088,"end":4270,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4271,"meta":4272,"organizer":4113,"start":4273,"stem":4274,"url":4113,"__hash__":4275},"events\u002Fevents\u002Fwebinar-live-2026-08-18.yaml",[4268],{"text":4220,"url":4269,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002F19d88cff-9268-4d32-9195-279ce8aa69c5@2865933d-64a6-4c0b-8170-1f161587b1df","2026-08-18T15:30:00+02:00",{"name":4227},{},"2026-08-18T15:00:00+02:00","events\u002Fwebinar-live-2026-08-18","H_vn2TTP_t-YbbnzDJ51VV2WzNeY2BkZZoQTLTwA4Us",{"id":4277,"title":4217,"callToAction":4278,"category":4206,"description":4224,"draft":4088,"end":4281,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4282,"meta":4283,"organizer":4113,"start":4284,"stem":4285,"url":4113,"__hash__":4286},"events\u002Fevents\u002Fwebinar-live-2026-09-01.yaml",[4279],{"text":4220,"url":4280,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002F03bbd9f4-0450-477c-be61-6c1331b0e9d8@2865933d-64a6-4c0b-8170-1f161587b1df","2026-09-01T15:30:00+02:00",{"name":4227},{},"2026-09-01T15:00:00+02:00","events\u002Fwebinar-live-2026-09-01","7BtMVrLLBufJbSYJhebVec9pA7cnD8CvOJHoLVIdDCs",{"id":4288,"title":4217,"callToAction":4289,"category":4206,"description":4224,"draft":4088,"end":4292,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4293,"meta":4294,"organizer":4113,"start":4295,"stem":4296,"url":4113,"__hash__":4297},"events\u002Fevents\u002Fwebinar-live-2026-09-15.yaml",[4290],{"text":4220,"url":4291,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002F1137d8e2-c467-411e-a353-8894e39e99b6@2865933d-64a6-4c0b-8170-1f161587b1df","2026-09-15T15:30:00+02:00",{"name":4227},{},"2026-09-15T15:00:00+02:00","events\u002Fwebinar-live-2026-09-15","-PPSokmGLLQ0o72andGRwnZC9Jm0WW8m5RXq93M0jaw",{"id":4299,"title":4217,"callToAction":4300,"category":4206,"description":4224,"draft":4088,"end":4303,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4304,"meta":4305,"organizer":4113,"start":4306,"stem":4307,"url":4113,"__hash__":4308},"events\u002Fevents\u002Fwebinar-live-2026-09-29.yaml",[4301],{"text":4220,"url":4302,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002Fe6a0bcdb-440d-42e4-b48f-0fb81f698a1c@2865933d-64a6-4c0b-8170-1f161587b1df","2026-09-29T15:30:00+02:00",{"name":4227},{},"2026-09-29T15:00:00+02:00","events\u002Fwebinar-live-2026-09-29","jfLtF-fINmuEl7vbJL5-XF09Figs-0dL2m85H9PPfos",{"id":4310,"title":4217,"callToAction":4311,"category":4206,"description":4224,"draft":4088,"end":4314,"extension":4118,"image":4113,"imageAlt":4113,"isAllDay":4088,"location":4315,"meta":4316,"organizer":4113,"start":4317,"stem":4318,"url":4113,"__hash__":4319},"events\u002Fevents\u002Fwebinar-live-2026-10-13.yaml",[4312],{"text":4220,"url":4313,"icon":4222,"target":4223},"https:\u002F\u002Fevents.teams.microsoft.com\u002Fevent\u002Feb8e5ad2-b83c-4375-9c3b-13f1b22c7cbb@2865933d-64a6-4c0b-8170-1f161587b1df","2026-10-13T15:30:00+02:00",{"name":4227},{},"2026-10-13T15:00:00+02:00","events\u002Fwebinar-live-2026-10-13","yhmbvMXUTITF-S28C9K0FvwezK6RBZuI6Zxw1P9yVMw",[4321,4326,4331,4336,4341,4346,4351,4356,4361,4366,4371,4376,4381,4386,4391,4396,4401,4406],{"title":4322,"icon":4323,"slug":4324,"stem":4325,"nav":2306,"hasDetailPage":2306,"draft":4088},"Bauelemente","hugeicons:door","bauelemente","crafts\u002Fbauelemente",{"title":4327,"icon":4328,"slug":4329,"stem":4330,"nav":2306,"hasDetailPage":2306,"draft":4088},"Boden- und Fliesenleger","icon-park-outline:floor-tile","fliesenleger","crafts\u002Fboden-und-fliesenleger",{"title":4332,"icon":4333,"slug":4334,"stem":4335,"nav":2306,"hasDetailPage":2306,"draft":4088},"Dachdecker & Zimmerer","material-symbols:roofing-outline-rounded","dachdecker","crafts\u002Fdachdecker",{"title":4337,"icon":4338,"slug":4339,"stem":4340,"nav":2306,"hasDetailPage":2306,"draft":4088},"Elektriker","ic:baseline-electrical-services","elektriker","crafts\u002Felektriker",{"title":4342,"icon":4343,"slug":4344,"stem":4345,"nav":2306,"hasDetailPage":2306,"draft":4088},"Fensterbauer","fluent-emoji-high-contrast:window","fensterbauer","crafts\u002Ffensterbauer",{"title":4347,"icon":4348,"slug":4349,"stem":4350,"nav":2306,"hasDetailPage":2306,"draft":4088},"Garten- und Landschaftsbauer","ph:tree-duotone","galabauer","crafts\u002Fgarten-und-landschaftsbauer",{"title":4352,"icon":4353,"slug":4354,"stem":4355,"nav":2306,"hasDetailPage":2306,"draft":4088},"Gerüstbauer","material-symbols-light:shelves-outline-rounded","geruestbauer","crafts\u002Fgeruestbauer",{"title":4357,"icon":4358,"slug":4359,"stem":4360,"nav":4088,"hasDetailPage":2306,"draft":4088},"Hausverwaltung","tabler:building-community","hausverwaltung","crafts\u002Fhausverwaltung",{"title":4362,"icon":4363,"slug":4364,"stem":4365,"nav":4088,"hasDetailPage":2306,"draft":4088},"Hoch- und Tiefbauer","fa6-solid:trowel-bricks","hoch-tiefbauer","crafts\u002Fhoch-und-tiefbauer",{"title":4367,"icon":4368,"slug":4369,"stem":4370,"nav":4088,"hasDetailPage":2306,"draft":4088},"Holzbauer","mdi:forest","holzbauer","crafts\u002Fholzbauer",{"title":4372,"icon":4373,"slug":4374,"stem":4375,"nav":4088,"hasDetailPage":2306,"draft":4088},"KFZ","mdi:car-wrench","kfz","crafts\u002Fkfz",{"title":4377,"icon":4378,"slug":4379,"stem":4380,"nav":4088,"hasDetailPage":2306,"draft":4088},"Maler und Lackierer","ri:paint-brush-line","maler-lackierer","crafts\u002Fmaler-und-lackierer",{"title":4382,"icon":4383,"slug":4384,"stem":4385,"nav":2306,"hasDetailPage":2306,"draft":4088},"Maschinen- und Anlagenbauer","tabler:settings-automation","maschinen-anlagenbauer","crafts\u002Fmaschinen-anlagenbauer",{"title":4387,"icon":4388,"slug":4389,"stem":4390,"nav":2306,"hasDetailPage":2306,"draft":4088},"Metallbauer und Schlosser","tabler:arrow-up","metallbauer","crafts\u002Fmetallbauer-und-schlosser",{"title":4392,"icon":4393,"slug":4394,"stem":4395,"nav":2306,"hasDetailPage":2306,"draft":4088},"Sanitär, Heizung, Klima","ic:baseline-plumbing","shk","crafts\u002Fsanitaer-heizung-klima",{"title":4397,"icon":4398,"slug":4399,"stem":4400,"nav":2306,"hasDetailPage":2306,"draft":4088},"Schreiner und Tischler","mdi:circular-saw","schreiner-tischler","crafts\u002Fschreiner-und-tischler",{"title":4402,"icon":4403,"slug":4404,"stem":4405,"nav":2306,"hasDetailPage":2306,"draft":4088},"Treppenbauer","tabler:stairs","treppenbauer","crafts\u002Ftreppenbauer",{"title":4407,"icon":4408,"slug":4113,"stem":4409,"nav":4088,"hasDetailPage":4088,"draft":4088},"und viele mehr...","ci:users-group","crafts\u002Fund-viele-mehr",[4411,4417,4422,4427],{"company":4412,"meta":4413,"logo":4414,"logoBackgroundColor":4415,"url":4416},"Ammann Treppen","Treppenbau · 60 Mitarbeiter","\u002Fimages\u002Fkunden\u002Fammann.svg","#ffffff","\u002Ferfolgsgeschichten\u002Fammann",{"company":4418,"meta":4419,"logo":4420,"logoBackgroundColor":4415,"url":4421},"Objekteinrichtung Hengelhaupt","Innenausbau · ~60 Mitarbeiter","\u002Ftestimonials\u002Fhengelhaupt\u002Flogo.webp","\u002Ferfolgsgeschichten\u002Fhengelhaupt",{"company":4423,"meta":4424,"logo":4425,"logoBackgroundColor":4415,"url":4426},"PEHA Reparatur und Anlagenbau","Anlagenbau · 21 Mitarbeiter","\u002Fimages\u002Fkunden\u002Fpeha.webp","\u002Ferfolgsgeschichten\u002Fpeha",{"company":4428,"meta":4429,"logo":4430,"logoBackgroundColor":4431,"url":4432},"Tahn Gerüstbau","Gerüstbau · 18 Mitarbeiter","\u002Ftestimonials\u002Ftahn\u002Flogo.svg","#202A6A","\u002Ferfolgsgeschichten\u002Ftahn",[4434,4438,4442,4446,4451,4456,4461,4466,4472,4477,4482,4487,4492,4497,4503,4508,4513,4518,4523,4528,4533,4538,4544,4549,4554,4559,4564,4568,4573,4579,4583,4588,4593,4598,4604,4609,4614,4617,4620,4625,4630,4634],{"title":1882,"icon":4435,"description":4436,"url":1881,"parentSlug":4437},"tabler:folder","Alles zum Auftrag an einem Ort","auftragsverwaltung",{"title":4161,"icon":4439,"description":4440,"url":4441,"parentSlug":4437},"tabler:calendar-time","Aufträge in Arbeitsschritte zerlegen","\u002Fauftragsverwaltung\u002Fauftragsplanung",{"title":4443,"icon":4358,"description":4444,"url":4445,"parentSlug":4437},"Baustellenplanung","Die ganze Laufzeit im Blick","\u002Fauftragsverwaltung\u002Fbaustellenplanung",{"title":4447,"icon":4448,"description":4449,"url":4450,"parentSlug":4437},"Kapazitätsplanung","tabler:chart-bar","Passt die Zusage überhaupt hinein?","\u002Fauftragsverwaltung\u002Fkapazitaetsplanung",{"title":4452,"icon":4453,"description":4454,"url":4455,"parentSlug":4437},"Projektmanagement","tabler:building-arch","Mehrere Bauvorhaben gleichzeitig","\u002Fauftragsverwaltung\u002Fprojektmanagement",{"title":4457,"icon":4458,"description":4459,"url":4460,"parentSlug":4437},"Standardabläufe","tabler:repeat","Wiederkehrendes einmal anlegen","\u002Fauftragsverwaltung\u002Fstandardablaeufe",{"title":4462,"icon":4463,"description":4464,"url":4465,"parentSlug":4437},"Terminplanung","tabler:calendar-event","Termine am Auftrag statt im Kalender","\u002Fauftragsverwaltung\u002Fterminplanung",{"title":4467,"icon":4468,"description":4469,"url":4470,"parentSlug":4471},"Auftragschat","tabler:message-circle","Absprachen statt Suche im WhatsApp-Verlauf","\u002Fdokumentation-kommunikation\u002Fauftragschat","dokumentation-kommunikation",{"title":4473,"icon":4474,"description":4475,"url":4476,"parentSlug":4471},"Auftragsstatus","tabler:progress-check","Wo steckt der Auftrag gerade?","\u002Fdokumentation-kommunikation\u002Fauftragsstatus",{"title":4478,"icon":4479,"description":4480,"url":4481,"parentSlug":4471},"Baustellendokumentation","tabler:crane","Lückenlos statt nachträglich rekonstruiert","\u002Fdokumentation-kommunikation\u002Fbaustellendokumentation",{"title":4483,"icon":4484,"description":4485,"url":4486,"parentSlug":4471},"Checklisten","tabler:list-check","Jeder Auftrag läuft gleich ab","\u002Fdokumentation-kommunikation\u002Fchecklisten",{"title":4488,"icon":4489,"description":4490,"url":4491,"parentSlug":4471},"Fotodokumentation","tabler:camera","Mit Fotos belegen, was vor Ort war","\u002Fdokumentation-kommunikation\u002Ffotodokumentation",{"title":4493,"icon":4494,"description":4495,"url":4496,"parentSlug":4471},"Handwerker-App","tabler:device-mobile","Stempeln ohne etwas zu installieren","\u002Fdokumentation-kommunikation\u002Fhandwerker-app",{"title":4498,"icon":4499,"description":4500,"url":4501,"parentSlug":4502},"Abnahmeprotokoll","tabler:checkbox","Abnahme belegen, Mängel festhalten","\u002Fformulare\u002Fabnahmeprotokoll","formulare",{"title":4504,"icon":4505,"description":4506,"url":4507,"parentSlug":4502},"Aufmaßblatt","tabler:ruler-measure","Maße, Skizze und Foto vor Ort","\u002Fformulare\u002Faufmassblatt",{"title":4509,"icon":4510,"description":4511,"url":4512,"parentSlug":4502},"Auftragsdatenblatt","tabler:file-description","Die Eckdaten für alle verfügbar","\u002Fformulare\u002Fauftragsdatenblatt",{"title":4514,"icon":4515,"description":4516,"url":4517,"parentSlug":4502},"Bautagesbericht","tabler:notebook","Wetter, Besetzung und Behinderungen je Tag","\u002Fformulare\u002Fbautagesbericht",{"title":4519,"icon":4520,"description":4521,"url":4522,"parentSlug":4502},"Digitale Unterschrift","tabler:signature","Auf dem Handy unterschreiben lassen","\u002Fformulare\u002Fdigitale-unterschrift",{"title":4524,"icon":4525,"description":4526,"url":4527,"parentSlug":4502},"Prüfprotokoll","tabler:clipboard-check","Prüfungen lückenlos belegen","\u002Fformulare\u002Fpruefprotokoll",{"title":4529,"icon":4530,"description":4531,"url":4532,"parentSlug":4502},"Regiebericht","tabler:receipt","Regiearbeiten nachweisbar abrechnen","\u002Fformulare\u002Fregiebericht",{"title":4534,"icon":4535,"description":4536,"url":4537,"parentSlug":4502},"Wartungsprotokoll","tabler:tool","Jede Wartung später nachvollziehbar","\u002Fformulare\u002Fwartungsprotokoll",{"title":4539,"icon":4540,"description":4541,"url":4542,"parentSlug":4543},"Disposition","tabler:arrows-shuffle","Störfälle ohne Umwerfen der Woche","\u002Fmitarbeiterplanung\u002Fdisposition","mitarbeiterplanung",{"title":4545,"icon":4546,"description":4547,"url":4548,"parentSlug":4543},"Einsatzplanung","tabler:layout-board","Wer ist wo, wer ist frei","\u002Fmitarbeiterplanung\u002Feinsatzplanung",{"title":4550,"icon":4551,"description":4552,"url":4553,"parentSlug":4543},"Kolonnenplanung","tabler:users-group","Eingespielte Trupps als Einheit planen","\u002Fmitarbeiterplanung\u002Fkolonnenplanung",{"title":4555,"icon":4556,"description":4557,"url":4558,"parentSlug":4543},"Montageplanung","tabler:tools","Vorfertigung, Team und Baustelle","\u002Fmitarbeiterplanung\u002Fmontageplanung",{"title":4560,"icon":4561,"description":4562,"url":4563,"parentSlug":4543},"Digitale Plantafel","tabler:table","Die Magnettafel für unterwegs","\u002Fmitarbeiterplanung\u002Fplantafel",{"title":4565,"icon":4535,"description":4566,"url":4567,"parentSlug":4543},"Serviceaufträge und Wartung","Wiederkehrende Termine und Störungen","\u002Fmitarbeiterplanung\u002Fserviceauftraege",{"title":4569,"icon":4570,"description":4571,"url":4572,"parentSlug":4543},"Werkstattplanung","tabler:building-factory-2","Bereiche, Maschinen und Vorfertigung","\u002Fmitarbeiterplanung\u002Fwerkstattplanung",{"title":4574,"icon":4575,"description":4576,"url":4577,"parentSlug":4578},"Abwesenheitskalender","tabler:calendar-month","Wer wann weg ist, auf einen Blick","\u002Furlaubsplanung\u002Fabwesenheitskalender","urlaubsplanung",{"title":4580,"icon":4463,"description":4581,"url":4582,"parentSlug":4578},"Abwesenheitsplanung","Urlaub direkt in der Einsatzplanung","\u002Furlaubsplanung\u002Fabwesenheitsplanung",{"title":4584,"icon":4585,"description":4586,"url":4587,"parentSlug":4578},"Berufsschule und Weiterbildung","tabler:school","Schultage und Lehrgänge früh einplanen","\u002Furlaubsplanung\u002Fberufsschule",{"title":4589,"icon":4590,"description":4591,"url":4592,"parentSlug":4578},"Krankmeldung","tabler:first-aid-kit","Wenn morgens um sieben jemand ausfällt","\u002Furlaubsplanung\u002Fkrankmeldung",{"title":4594,"icon":4595,"description":4596,"url":4597,"parentSlug":4578},"Urlaubsantrag","tabler:file-check","Per App beantragen, per Klick freigeben","\u002Furlaubsplanung\u002Furlaubsantrag",{"title":4599,"icon":4600,"description":4601,"url":4602,"parentSlug":4603},"Arbeitszeiterfassung Pflicht","tabler:scale","Was dokumentiert werden muss","\u002Fzeiterfassung\u002Farbeitszeiterfassung-pflicht","zeiterfassung",{"title":4605,"icon":4606,"description":4607,"url":4608,"parentSlug":4603},"Arbeitszeitkonto","tabler:hourglass","Soll gegen Ist, Monat für Monat","\u002Fzeiterfassung\u002Farbeitszeitkonto",{"title":4610,"icon":4611,"description":4612,"url":4613,"parentSlug":4603},"GPS-Zeiterfassung","tabler:map-pin","Standort beim Stempeln, ohne Dauerortung","\u002Fzeiterfassung\u002Fgps-tracking",{"title":1530,"icon":4615,"description":4616,"url":1529,"parentSlug":4603},"tabler:calculator","Was der Auftrag wirklich gekostet hat",{"title":1535,"icon":4618,"description":4619,"url":1534,"parentSlug":4603},"tabler:briefcase","Welche Stunden auf welchem Auftrag",{"title":4621,"icon":4622,"description":4623,"url":4624,"parentSlug":4603},"Rapportzettel","tabler:clipboard-text","Leistung vor Ort unterschreiben lassen","\u002Fzeiterfassung\u002Frapportzettel",{"title":4626,"icon":4627,"description":4628,"url":4629,"parentSlug":4603},"RFID-Zeiterfassung","tabler:id","Stempeln per Chip am Terminal","\u002Fzeiterfassung\u002Frfid",{"title":4631,"icon":4632,"description":4633,"url":1524,"parentSlug":4603},"Digitaler Stundenzettel","tabler:file-text","Grundlage für Lohn und Nachkalkulation",{"title":4635,"icon":4636,"description":4637,"url":4638,"parentSlug":4603},"Überstunden","tabler:clock-plus","Sehen, wer wie viel geschoben hat","\u002Fzeiterfassung\u002Fueberstunden",[4640,4643,4646,4649,4651,4654,4656,4659],{"title":4641,"stem":4642,"hasDetailPage":2306},"Excel \u002F CSV","apis\u002Fexcel",{"title":4644,"stem":4645,"hasDetailPage":4088},"HubSpot","apis\u002Fhubspot",{"title":4647,"stem":4648,"hasDetailPage":2306},"Kalender","apis\u002Fkalender",{"title":4017,"stem":4650,"hasDetailPage":2306},"apis\u002Flexware-office",{"title":4652,"stem":4653,"hasDetailPage":2306},"Moser Mosaik","apis\u002Fmosaik",{"title":136,"stem":4655,"hasDetailPage":2306},"apis\u002Fn8n",{"title":4657,"stem":4658,"hasDetailPage":2306},"Pinncalc Corpora","apis\u002Fpinncalc-corpora",{"title":20,"stem":4660,"hasDetailPage":2306},"apis\u002Frest-api",1788418964344]