Dokumentation
To veje ind.
Én vej ud til printeren.
Denne side er til den, der skal koble systemet på. Nedenfor står kaldet, kvitteringen, idempotensreglen — og feltspecifikationen for den Interline-CSV, jeres system skriver i dag, felt for felt, som vi faktisk læser den.
Filen i mappen
WeLabel henter filerne fra den server, jeres system skriver dem på i dag — samme format, samme placering. Print-agenten ser dem aldrig; den printer kun. Feltspecifikationen står i afsnit 5.
Direkte til API’etKommer
Har I en udvikler og rører alligevel ved webshoppen, kan ordren sendes direkte. Etiketten går den samme vej ud til printeren bagefter. Kaldet er endnu ikke åbnet — afsnit 1–4 viser den form, vi bygger efter.
GLS-oplysninger bliver hos os
Jeres GLS-brugernavn og -kodeord ligger krypteret på jeres konto og bruges kun af WeLabel. De skal aldrig sendes med i kaldet, og print-agenten kender dem ikke.
Print-agenten ved pakkebordet
Et lille program, der henter printkøen hos WeLabel og sender etiketten direkte til jeres Zebra. Det holder hverken ordrefiler eller GLS-oplysninger.
Windows
- 64-bit Windows.
- Kører som Windows-tjeneste, også når ingen er logget ind.
- Printer til en Zebra på netværket over TCP port 9100 eller gennem Windows’ printerkø.
MacSnart
- macOS 13 Ventura eller nyere, på Apple Silicon og Intel.
- Kører som baggrundstjeneste.
- Printer kun til en Zebra på netværket over TCP port 9100. USB-printere understøttes endnu ikke på Mac.
- Går Mac’en i dvale, henter agenten køen, når den vågner igen.
Mac-versionen er klar og kommer ud i en signeret udgave snarest.
Afsnit 1–4 beskriver et API, der endnu ikke er åbnet.
De står her, fordi I skal kunne se, hvad I senere kobler jer på — men de beskriver den form, vi bygger efter, ikke en tjeneste, I kan kalde i dag. POST /api/v1/shipments svarer i skrivende stund 501 og kan kun nås fra en indlogget session. API-nøgler findes endnu ikke, så Authorization: Bearer nedenfor er et forslag, ikke en beskrivelse. Skriver I integrationen efter afsnit 1–4 i dag, bygger I på et gæt.
Afsnit 5 er noget andet. Feltspecifikationen for Interline-CSV’en er målt på rigtige filer og gælder i dag. Skal I bygge på noget nu, så byg på den — og skriv til os, så siger vi til, når kaldet og nøglerne står fast.
01
KommerAutentificering
Én API-nøgle pr. organisation, oprettet i dashboardet. Den sendes i Authorization-headeren — aldrig i URL’en, hvor den ender i jeres egne adgangslogs.
Nøglen vises én gang ved oprettelsen. Bliver den væk, laver I en ny og sletter den gamle; begge kan være aktive imens, så I kan skifte uden at stoppe pakkebordet.
Authorization: Bearer wl_live_7Q2K…9ZTV Content-Type: application/json; charset=utf-8 Idempotency-Key: 10482-0
02
KommerOpret en forsendelse
Ét kald pr. ordre. Vi oversætter til GLS’ nye Label API med jeres egne GLS-oplysninger, gemmer etiketten og lægger printjobbet i kø til den printer, I har valgt.
Kaldet
{
"orderId": "10482",
"shipmentDate": "2026-09-14",
"delivery": {
"name1": "Mette Sørensen",
"street1": "Nørrebrogade 42, 3. th",
"zipcode": "2200",
"city": "København N",
"country": "DK",
"email": "mette@example.dk",
"mobile": "+45 20 12 34 56"
},
"parcels": [
{ "index": 0, "weight": 1.4 }
],
"services": [
{ "type": "ShopDelivery",
"value": "2760 4001" }
],
"labelFormat": "zpl"
}{
"shipmentId": "shp_8Q2K4M7ZTV",
"orderId": "10482",
"status": "afventer_print",
"parcels": [
{
"index": 0,
"parcelNumber": "052300091234",
"labelFormat": "zpl",
"printer": "PAKKEBORD-01"
}
],
"carrier": "gls-dk",
"traceId": "b41f…c7a2",
"createdAt":
"2026-09-14T09:41:12Z"
}Hvad I får tilbage
Pakkenummeret, med det samme. Etiketten selv ligger hos os og printes af agenten — I skal ikke håndtere ZPL for at printe.
Gem traceId
Det er GLS’ eget spor på kaldet, og det eneste håndtag GLS’ support tager imod. Vi gemmer det også selv i 90 dage.
Bemærk orderId
Det bliver til GLS’ eget Reference-felt, som højst må fylde 15 tegn. Er jeres ordrenumre længere, siger vi det ved oprettelsen frem for at klippe dem af i stilhed.
03
KommerIdempotens
Nøglen er ordrenummer + pakkeindeks. Sender I det samme kald igen — fordi jobbet blev kørt to gange, eller fordi netværket faldt ud midt i svaret — får I den forsendelse tilbage, der allerede findes. Der oprettes ikke en pakke mere.
Sætter I selv Idempotency-Key, bruger vi jeres. Gør I ikke, danner vi den af de to felter.
Vi prøver aldrig et kald igen, der kan være gået igennem
GLS’ API har ingen idempotens i sin ende. Svarer det ikke i tide, ved ingen, om pakken blev oprettet. Så gætter vi ikke: forsendelsen får status afklaring_paakraevet, og et menneske afgør, hvad der skal ske. Det er derfor, I aldrig betaler for den samme pakke to gange.
{
"shipmentId": "shp_8Q2K4M7ZTV",
"status": "afklaring_paakraevet",
"message": "GLS svarede ikke i tide.
Pakken findes måske allerede — vi
opretter den ikke igen af os selv."
}04
KommerSvar og fejl
Et afvist kald har både en code, som jeres kode kan skifte på, og en message, som et menneske kan læse højt i telefonen.
| Status | Betydning |
|---|---|
| 400 | Kaldet mangler et felt, GLS kræver — typisk vægt, e-mail eller mobil. Vi siger hvilket, og hvorfor det er obligatorisk for den valgte service. |
| 401 | API-nøglen mangler, er forkert eller er slettet. |
| 402 | Nøglen er god nok — kontoen skal ses til. Ikke 403, netop for at ingen begynder at fejlsøge sin API-nøgle. Koderne står nedenfor. |
| 422 | GLS afviste forsendelsen. GLS’ egen besked og traceId følger med uændret. |
| 202 | Modtaget, men endnu ikke afgjort — enten fordi GLS ikke svarede i tide, eller fordi forsendelsen står i kø under en forstyrrelse. Intet går tabt, og intet skal skrives ind igen. |
proeve_udloebetPrøveperioden er udløbet.
proeve_opbrugtDe 100 prøveetiketter er brugt.
abonnement_ubetaltBetalingen kunne ikke trækkes.
abonnement_paa_pauseAbonnementet er sat på pause.
abonnement_ophoertAbonnementet er ophørt.
ingen_kontoIngen aktiv plan på kontoen.
En etiket, der allerede er hentet hos GLS, kan altid printes igen — genudskrivning bliver aldrig afvist af de her koder. En pakke, I har betalt for, skal kunne komme ud af printeren.
05
Interline-CSV’en, felt for felt.
Det er den fil, jeres system skriver i dag. Den skal ikke laves om. Kolonnen til højre er, hvad feltet bliver til i GLS’ nye Label API.
Aflæst af rigtige filer
Specifikationen nedenfor er målt på 427 anonymiserede ordrefiler fra en shop, der kører Interline i dag — ikke læst i en manual.
Tegnsæt
ISO-8859-1
358 af 427 filer har tegn over 0x7F. Læses de som UTF-8, går hvert ø og å i stykker.
Struktur
22 felter, 1 ordre
Én række pr. fil, ingen headerrække, linjeskift kun LF.
Anførselstegn
Ved mellemrum og komma
2 af 427 filer har et komma inde i vejnavnet. Splittes der på komma, flytter hele adressen sig — uden at noget fejler.
Returfil
KommerKommer
Valgfri, og skrevet af WeLabel når etiketten er printet — aldrig af pakke-PC’en. Den er ikke bygget endnu: læser jeres system den, så sig til inden I skifter, så aftaler vi formen.
| # | Felt | Hvad vi ser i filerne | Bliver til |
|---|---|---|---|
| 0 | Ordrenummer | Aldrig tom. Står også i filnavnet | Reference — højst 15 tegn i det nye API |
| 1 | Name1Åbent | Modtagerens firmanavn, ellers modtagerens navn — men pakkeshoppens navn, når felt 13 er Z. Se afsnit 6 | Delivery.Name1 |
| 2 | Street1Åbent | Begge adresselinjer, allerede sat sammen med et mellemrum — men pakkeshoppens vej, når felt 13 er Z. Kan indeholde komma inde i anførselstegn | Delivery.Street1 — højst 40 tegn |
| 3 | Region | Tom i alle 427 filer. Bliver ikke skiftet ud på en pakkeshop-række — den hører til kunden | Ingen modtager i det nye API |
| 4 | PostnrÅbent | Pakkeshoppens postnr., når felt 13 er Z | Delivery.Zipcode |
| 5 | ByÅbent | Pakkeshoppens by, når felt 13 er Z | Delivery.City |
| 6 | Landekode | 30 = SE (361 filer) · 28 = NO (66) · 8 er Danmark | Delivery.Country som ISO — aldrig koden selv |
| 7 | Dato | DD-MM-YY | ShipmentDate som YYYY-MM-DD |
| 8 | VægtÅbent | Kilo, med komma: 1,5. Altid 1 i materialet — se afsnit 6 | Parcels[].Weight — obligatorisk i det nye API |
| 9 | Antal kolli | Altid 1 i materialet | Antal Parcels[] |
| 10 | — | Tom i alle filer | Ignoreres |
| 11 | — | Tom i alle filer | Ignoreres |
| 12 | Pakketype | A i alle filer. M betyder privatlevering, og det er dét felt — ikke felt 13 — der siger det | M bliver til PrivateDelivery — vores læsning, afventer bekræftelse. A tilføjer ingen service |
| 13 | Service | Z = pakkeshop (359) · U = modtageren ligger uden for Danmark (67) · A = alt andet, og dermed alt indenlandsk · B og 2 = returetiket | ShopDelivery ved Z. A og U er levering til adressen i filen. Returetiketter laver vi endnu ikke — de standser |
| 14 | Afhentningsnavn | Kundens eget navn — for- og efternavn fra leveringsadressen. Udfyldt i alle pakkeshop-rækker | Delivery.Contact — på en pakkeshop-række er det det eneste, filen siger om kunden ud over mail og mobil |
| 15 | Kommentar | Tom i alle filer | Parcels[].Comment |
| 16 | Afsenders GLS-kundenummer | Én værdi i alle 427 filer. Kan variere mellem filer fra samme sted, hvis I har sat forskellige numre op pr. bruger | Ikke et felt i kaldet — vælger hvilken GLS-aftale filen hører til |
| 17 | Aldrig tom | Delivery.Email — obligatorisk for begge services | |
| 18 | Mobil | Aldrig tom. Nogle gange i anførselstegn, fordi den indeholder mellemrum | Delivery.Mobile — obligatorisk for begge services |
| 19 | Servicetekst | Altid E i materialet | Ingen bekræftet modtager — gemmes uændret |
| 20 | Bruger | Tom i alle filer. Udfyldes kun, hvis I slår det til | Kun til revisionsloggen |
| 21 | Pakkeshop-ID | Tom i præcis de 67 U-rækker, udfyldt i alle 360 øvrige | ShopDeliverys værdi |
Felt 13 vælger leveringsformen, og felt 21 er dens pakkeshop-argument: Tom i præcis de 67 U-rækker, udfyldt i alle 360 øvrige— også i den ene række med servicekode 2, som ikke er en pakkeshop-forsendelse. Bemærk, at U ikke betyder privat levering — det skrives, når modtageren ligger uden for Danmark. Privat levering står i felt 12 som M. Ser jeres egen fil anderledes ud, sender I den til os, og så måler vi på den i stedet for at gætte.
Er jeres webshop sat op til at sende sin egen afsenderadresse med, står der 29 felter på linjen i stedet for 22: de samme som ovenfor plus navn, adresse, postnr., by, land og telefon på afsenderen. Begge længder læses. Alt andet standser filen frem for at læse den skævt.
06
To ting vi endnu ikke ved.
Begge er spørgsmål, der skal besvares af GLS, og begge står her, fordi I skal kunne se, hvad vi gør i mellemtiden. De står også åbne i vores egen dokumentation.
Pakkeshoppens adresse står, hvor kundens skulle stå
Når felt 13 er Z, skriver jeres webshop pakkeshoppens navn, vej, postnr. og by i felt 1, 2, 4 og 5 — kundens egen adresse bliver skrevet over, inden filen bliver gemt. Filen indeholder altså ingen kundeadresse på en pakkeshop-forsendelse — kun navn i felt 14, mail og mobil. Det gælder 359 af de 427 filer. Spørgsmålet til GLS er, om det nye API kan nøjes med det, når pakkeshoppen i forvejen er valgt på id — eller om det vil have kundens egen adresse ved siden af.
Indtil da: vi sender det, filen faktisk siger — pakkeshoppens adresse som leveringsadresse, kunden som kontakt — og vi finder aldrig på en adresse, filen ikke indeholder. Sender I direkte til API’et, sender I begge dele og er ikke berørt.
Vægten er 1 — men er den vejet?
Felt 8 er vægten i kilo, skrevet med komma: 1,5 er halvandet kilo. Alle 427 filer bærer 1 — og det tal er ikke nødvendigvis vejet: webshoppen skriver 1, når varerne ikke har en vægt sat. Parcels[].Weight er obligatorisk i det nye API, så spørgsmålet til GLS er, hvad et deklareret kilo betyder for pris og kontrol.
Indtil da: står der en vægt i filen, bruger vi den — også med decimaler. Står der præcis 1, kan I under Indstillinger sætte en standardvægt på forbindelsen, som vi sender i stedet; sætter I ingen, sender vi filens 1 uændret. Er feltet tomt, står forsendelsen uden vægt hos os; vi finder ikke på et tal. Ingen af de 427 filer har et tomt vægtfelt. Sender I direkte til API’et, angiver I vægten i kaldet og er ikke berørt.