# Webtrebol – fuld dokumentation
# Eget domæne
(https://docs.webtrebol.dk/backoffice/eget-domaene/)
Du skal kunne køre fra shoppens eget domæne og nemt sætte det op.
## Status
Domæne-API'et og sektionen i Indstillinger er bygget. Platformens domæneopsætning er endnu ikke slået til, så sektionen viser en venlig besked i stedet for en kontrol. Det forventes åbnet i fase 2 af [roadmappen](site:/udvikling/).
## Det planlagte flow
1. Skriv dit domæne i Indstillinger.
2. Platformen viser, hvilke DNS-poster du skal oprette.
3. Platformen tjekker, at domænet peger rigtigt.
Husk, at en selvhostet storefront kører på sit eget domæne uafhængigt af dette. Se [Publicér selv](/storefront/publicer-selv/).
---
# Fortrydelser og refusioner
(https://docs.webtrebol.dk/backoffice/fortrydelser/)
Når en kunde fortryder via ordre-linket, dukker sagen op under **Fortrydelser**.
## Din rolle
1. Se sagen og de linjer og mængder, kunden fortryder.
2. Når varen er modtaget, markerer du **vare modtaget** og vælger, om lageret skal genopfyldes.
3. Afslut med **refunderet** – eller **afvist**, hvis en lovlig undtagelse gælder.
## Frister
Platformen kender markedets frister (fortrydelse, refusion og besked til betalingsudbyderen) og sender påmindelser, så du ikke overser dem. Se [Fortrydelse](/storefront/fortrydelse/) for kundens side.
---
# Go-live-tjekliste
(https://docs.webtrebol.dk/backoffice/go-live/)
Dashboardet og Indstillinger viser en tjekliste over, hvad der mangler. Punkterne linker direkte til det rigtige sted.
## Tjeklisten
- **Forretning:** juridisk navn, CVR eller NIT (med kontrolciffer i Colombia) og adresse. Oplysningerne vises for kunderne og på kvitteringen.
- **Kontakt:** en support-e-mail og op til fem e-mails, der får besked om nye ordrer.
- **Returpolitik:** hvad du tilbyder ud over den lovpligtige fortrydelse.
- **Betaling:** en forbundet betalingskonto (fx Wompi), eller betaling ved levering.
- **Fragt:** mindst én fragtsats, så kunderne kan vælge levering.
- **Login med Google** (valgfrit): shoppens Google client-ID.
## For danske shops med egen storefront
Her skal ejeren også bekræfte, at storefrontens checkout opfylder [kravlisten](/storefront/kravliste/) og at [conformance-testen](/storefront/conformance-test/) er kørt {{badge:plan}}.
---
# Indstillinger
(https://docs.webtrebol.dk/backoffice/indstillinger/)
Indstillinger er delt i sektioner, og **hver sektion gemmes for sig**. Der er ingen global gem-knap.
| Sektion | Indhold |
|---|---|
| Forretning | Juridisk navn, CVR/NIT, adresse |
| Kontakt | Support-e-mail og ordre-notifikationer |
| Returpolitik | Tilbud ud over den lovpligtige fortrydelse |
| Betaling ved levering | Til/fra, maksbeløb og tilladte regioner |
| Fragt | Zonesatser, resten af landet og gratis fragt over et beløb |
| Betalingsudbyder | Dine nøgler til fx Wompi (gemmes krypteret) |
| Google-login | Shoppens Google client-ID |
| Eget domæne | Se [Eget domæne](/backoffice/eget-domaene/) {{badge:wip}} |
| Mail-afsender | Afsenderadresse til shoppens e-mails {{badge:wip}} |
Backoffice kan vises på dansk, engelsk og spansk.
---
# Opret en shop
(https://docs.webtrebol.dk/backoffice/opret-shop/)
Selvbetjent oprettelse er bygget, men **holdt lukket i pilotfasen**. I dag oprettes nye shops af os. Når den åbnes, ser flowet sådan ud.
## Flowet
1. Vælg **Opret en shop** på loginsiden.
2. Skriv shoppens navn. Adressen (slug) foreslås og tjekkes live for ledighed.
3. Vælg marked (Colombia eller Danmark).
4. Skriv ejerens e-mail og en adgangskode.
5. Du lander logget ind på dashboardet.
Resten af opsætningen sker i **Indstillinger** og følges af [Go-live-tjeklisten](/backoffice/go-live/).
## Har du allerede en konto?
Så vælger du **Opret ny shop** i sidemenuen. Du kan skifte mellem dine shops i samme menu uden at logge ind igen.
---
# Ordrer
(https://docs.webtrebol.dk/backoffice/ordrer/)
## Statusser
| Status | Betydning |
|---|---|
| `pending_payment` | Ordren er oprettet; betalingen er ikke bekræftet. |
| `confirmed` | Betalingen er bekræftet (eller kunden valgte betaling ved levering). |
| `shipped` | Markeret som sendt. |
| `delivered` | Markeret som leveret. |
Når du markerer en ordre som sendt eller leveret, starter fortrydelsesfristen, hvor reglerne kræver det.
## Betaling ved levering
Ved betaling ved levering bekræftes ordren, når kunden vælger metoden. Du markerer senere, at kontanterne er modtaget, eller at leveringen mislykkedes. Mislykket levering annullerer ordren og lægger varerne tilbage på lager.
## Redigér ordrer
Ordrer kan redigeres inden for afgrænsede regler. Beløb og linjer er uforanderlige efter oprettelsen, så ændringer sker som kontrollerede handlinger.
## Betalinger der skal refunderes
En for sen, dobbelt eller forkert betaling markeres `refundRequired`, så du kan finde og refundere den.
---
# Produkter og varianter
(https://docs.webtrebol.dk/backoffice/produkter/)
## Produkter og varianter
Et produkt kan have varianter. Størrelse og farve vælges som separate valgmuligheder (chips) i stedet for fri tekst. Hver variant har sin egen pris og sit eget lager.
## Kategorier
Kategorier er et fladt hierarki. Sletter du en kategori, rykker dens underkategorier op i stedet for at blive slettet.
## Billeder
Upload billeder pr. produkt. De vises i backoffice og i storefronten.
## Priser og moms
Priser indtastes og gemmes i mindste enhed. I Colombia er priser normalt inklusive IVA, og moms sættes pr. produkt (0, 5 eller 19 %). I Danmark er momsen 25 %.
---
# Team og roller
(https://docs.webtrebol.dk/backoffice/team-og-roller/)
Under **Team** inviterer du medarbejdere og vælger deres rolle.
- Kun **ejeren** kan ændre team og roller.
- Den sidste ejer kan ikke fjernes, så en shop aldrig står uden ejer.
- Medarbejdere kan logge ind med e-mail og adgangskode, og med Google, hvis det er sat op.
- Har du adgang til flere shops, skifter du mellem dem i sidemenuen.
---
# Betaling ved levering
(https://docs.webtrebol.dk/integrationer/betaling-ved-levering/)
*Pago contra entrega* lader kunden betale ved levering.
## Indstillinger
Under **Indstillinger → Betaling ved levering** kan du:
- slå metoden til og fra,
- sætte et maksimalt ordrebeløb,
- vælge hvilke departementer der må bruge den.
## Flowet
1. Kunden vælger metoden i checkout; ordren bliver straks `confirmed`.
2. Efter levering markerer du **kontant modtaget**.
3. Mislykkes leveringen, markerer du det, og ordren annulleres med varerne tilbage på lager.
---
# E-fakturering (DIAN)
(https://docs.webtrebol.dk/integrationer/dian/)
For colombianske shops kræves elektronisk fakturering (*factura electrónica*) til DIAN.
## Planen
- Fakturering sker gennem en **autoriseret udbyder** bag en adapter. Vi bygger ikke fakturering selv.
- IVA er allerede pr. linje, og priser er inklusive IVA.
- Den nuværende PDF-kvittering er **ikke en faktura**.
Funktionen er planlagt til Colombia-sporet og blokerer ikke lanceringen i Danmark.
---
# Fragt og kurerer
(https://docs.webtrebol.dk/integrationer/fragt/)
## Zonepriser
Hver shop kan sætte faste fragtsatser pr. region, en sats for resten af landet og gratis fragt over et beløb. Serveren priser fragten, og valget frosses på ordren og vises på kvitteringen. En shop kan ikke gå live uden fragtsatser.
## Flere kurerer {{badge:wip}}
Fundamentet er bygget: en generisk kurer-grænseflade, forbindelse af flere kurerer samtidigt pr. shop og krypteret lagring af nøgler. Der er endnu ingen rigtig kurer-forbindelse, der opretter forsendelser eller henter sporing.
## Planlagte kurerer {{badge:plan}}
| Marked | Kurerer |
|---|---|
| Colombia | Interrapidísimo, Servientrega, Coordinadora |
| Danmark | GLS, PostNord, Bring |
Vi vælger bevidst direkte forbindelser frem for en betalt mellemmand, så shopejeren selv kan forbinde sine kurerer.
---
# Google-login
(https://docs.webtrebol.dk/integrationer/google-login/)
## Kunder
Sæt shoppens Google client-ID under **Indstillinger**. Storefronten sender kundens Google ID-token til `POST /auth/google`. Platformen verificerer tokenet og bruger Googles `sub` som nøgle.
- Eksisterende konti kobles kun automatisk, når e-mailen er verificeret af Google (Gmail eller Workspace). Ellers kræves adgangskoden.
- Der er beskyttelse mod, at en anden overtager en konto, før ejeren har logget ind.
`GET /auth/config` fortæller storefronten, om Google-login er slået til.
## Medarbejdere
Medarbejdere kan logge ind i backoffice med Google. Det kræver en platform-bred Google client-ID på serveren.
---
# E-mail
(https://docs.webtrebol.dk/integrationer/mail/)
Platformen sender e-mails, uanset hvilken frontend der bruges: ordrebekræftelse, kvittering, og mails til kontoer (nulstilling af adgangskode, bekræftelse af e-mail) samt fortrydelsesbekræftelse.
## Status
Afsendelsen er bygget, og alle mails lægges først i en udbakke i samme transaktion som ordren. Selve udsendelsen slås til, når vores mailopsætning (afsenderdomæne med SPF og DKIM) er på plads.
## Mail-afsender
Pr. shop kan afsenderadressen sættes under Indstillinger {{badge:wip}}.
> [!NOTE] Marketingmails er ikke en del af første udgave. Samtykke og afmelding bygges, før de tilføjes.
---
# Stripe og MobilePay
(https://docs.webtrebol.dk/integrationer/stripe/)
Stripe er den første betalingsudbyder til Danmark og resten af EU. Shopejeren bruger sin egen Stripe-konto.
## Status
- **Stripe-adapteren er bygget** og indgår i platformen.
- Den er endnu **ikke afsluttet og godkendt til rigtige betalinger**. Vi afventer en Stripe-testkonto og et juridisk grundlag for danske shops.
- **MobilePay** tilbydes via Stripe og er planlagt {{badge:plan}}.
## Designet
Kortdata indtastes i Stripes eget felt (Payment Element), så hverken platformen eller shopejeren håndterer kortnumre. Betalingen bekræftes af en webhook, præcis som hos [Wompi](/integrationer/wompi/).
> [!NOTE] Indtil adapteren er åbnet, har danske shops endnu ikke online betaling.
---
# Wompi
(https://docs.webtrebol.dk/integrationer/wompi/)
Wompi er betalingsgatewayen til det colombianske marked. Shopejeren bruger sin egen Wompi-konto.
## Opsætning
1. Opret en Wompi-konto.
2. Læg dine nøgler ind under **Indstillinger → Betalingsudbyder**. De gemmes krypteret og vises aldrig igen.
3. Betalingskontoen tæller med i [go-live-tjeklisten](/backoffice/go-live/).
## Sådan virker det
- Kunden betaler i Wompis eget felt: enten via redirect eller en indlejret widget. Se [Betaling](/storefront/betaling/).
- Platformen bekræfter betalingen via en verificeret webhook (kontrolsum og beløbstjek) og en periodisk afstemning.
- Duplikerede hændelser giver ikke dobbelte ordrer.
## Betalingsmetoder
Kort, PSE og Nequi tilbydes gennem Wompi. Betaling ved levering er en separat metode: [Betaling ved levering](/integrationer/betaling-ved-levering/).
---
# Arkitektur i overblik
(https://docs.webtrebol.dk/kom-i-gang/arkitektur/)
Platformen er en **headless, multi-tenant, lagdelt modulær monolit**. Det betyder: ét API, ét backoffice, én database – og frontends, der er helt adskilt fra resten.
## Lagene
1. **Routes** modtager forespørgsler, validerer input og kalder en service. Ingen forretningsregler her.
2. **Services** ejer forretningsreglerne og er det eneste lag, der taler med databasen.
3. **Domænet** kender kun grænseflader (betaling, fragt, markedspakke) – aldrig en bestemt udbyder.
4. **Adaptere** er de konkrete forbindelser til Wompi, Stripe, kurerer, e-mail osv.
## Isolering mellem shops
Hver række i databasen har et `tenant_id`, og databasen håndhæver med *Row Level Security*, at en forespørgsel kun ser sin egen shops rækker. Isolationen dækkes af automatiske tests.
## Teknologi
TypeScript overalt. API: Node.js og Fastify. Database: PostgreSQL med Drizzle. Backoffice: React (Vite) med Tailwind. Storefront-skabelon: Next.js.
## Principper der beskytter dig som frontend-bygger
- **Serveren regner.** Pris, moms, fragt, lager og totaler beregnes altid i API'et. En frontend kan ikke ændre dem.
- **Ordrer er uforanderlige**, når de er oprettet.
- **Betaling bekræftes kun af udbyderen** (webhook eller afstemning) – aldrig af browseren.
- **`/v1` ændres kun additivt.** En selvhostet frontend skal ikke gå i stykker, fordi vi opdaterer.
---
# Begreber
(https://docs.webtrebol.dk/kom-i-gang/begreber/)
## Shop og tenant
En **shop** er én butik med eget domæne, sprog, valuta og egne indstillinger. Teknisk kaldes den en **tenant**. Al data hører til en tenant, og databasen sørger for, at en tenant aldrig kan læse en andens data.
## Backoffice
Det administrative program (`admin.webtrebol.dk`), hvor ejer og team styrer produkter, ordrer og indstillinger. Én konto kan have adgang til flere shops og skifte mellem dem.
## Storefront
Den kundevendte butik. Den taler kun med API'et og har ingen egen database.
## Publishable key
En offentlig nøgle, der fortæller API'et, hvilken shop en storefront hører til. Den må ligge i frontend-koden. Se [Autentificering](/storefront/autentificering/).
## Markedspakke
Alle regler for ét land samlet ét sted: valuta, moms, adresseformat, helligdage, fortrydelsesfrister og dokumenter. I dag findes Colombia og Danmark. Se [Markeder](/markeder/oversigt/).
## Adapter
En udskiftelig forbindelse til en ekstern tjeneste, fx betaling (Wompi, Stripe), fragt eller e-mail. Kernen kender kun adapterens grænseflade, så en ny udbyder kan tilføjes uden at ændre resten.
## Mindste enhed
Beløb gemmes og sendes som hele tal i valutaens mindste enhed (felter hedder fx `totalMinor`). Moms gemmes i basispoint. Der bruges aldrig kommatal til penge.
## BYOK
*Bring your own key.* Shopejeren bruger sin egen konto hos betalingsudbyderen og lægger sine egne nøgler ind i backoffice. Pengene går direkte til shopejeren.
---
# Hvad er Webtrebol
(https://docs.webtrebol.dk/kom-i-gang/hvad-er-webtrebol/)
Webtrebol er en platform til at lave mange webshops ud fra ét fundament. Platformen leverer et færdigt **backoffice** og et **API**. Du bygger kun **frontenden** – den del kunderne ser.
## Hvad platformen leverer
- Backoffice til produkter, ordrer, kunder, fortrydelser, team og indstillinger.
- Et versioneret REST-API (`/v1`) til katalog, kurv, checkout, ordrer og kvitteringer.
- Betaling, fragt, e-mail og login bag udskiftelige adaptere.
- Regler pr. marked: valuta, moms, adresser, helligdage og fortrydelsesfrister.
- Isolerede data pr. shop – flere shops kan køre på samme platform uden at se hinandens data.
## Hvad du selv bygger
Selve butikken: design, sider og oplevelse. Du kan bruge vores Next.js-skabelon som udgangspunkt, bygge noget helt eget, eller lade en AI bygge det ud fra denne dokumentation.
## Hvem hoster hvad
| Del | Hvem hoster |
|---|---|
| API og backoffice | Webtrebol |
| Din storefront (frontend) | Dig selv – fx Vercel, Netlify eller Cloudflare |
| Betalingsside/-widget | Betalingsudbyderen (Wompi, Stripe) |
Checkout kører altså på **dit** domæne, men kortdata rører aldrig dig eller os. Se [Ansvar og designfrihed](/storefront/oversigt/).
## Næste skridt
1. Læs [Begreber](/kom-i-gang/begreber/), så ordene er på plads.
2. Vil du bygge en frontend? Gå til [Byg en storefront](/storefront/oversigt/).
3. Skal du drive en shop? Gå til [Go-live-tjekliste](/backoffice/go-live/).
---
# Colombia
(https://docs.webtrebol.dk/markeder/colombia/)
| Emne | Pakken |
|---|---|
| Valuta | COP, hele pesos (ingen centavos) |
| Moms | IVA 0 / 5 / 19 % pr. produkt; priser normalt inkl. IVA |
| Adresse | Departamento og municipio fra DANE-listen: 33 departementer og 1.120 kommuner |
| Virksomhed | NIT med kontrolciffer (DV) og razón social |
| Fortrydelse | 5 hverdage, regnet med colombiansk helligdagskalender |
| Betaling | [Wompi](/integrationer/wompi/) og [betaling ved levering](/integrationer/betaling-ved-levering/) |
| Sprog | Colombiansk spansk som standard |
## Checkout
Private kunder behøver ikke angive personligt ID. Ved virksomhedskøb angives NIT og DV (valideret) samt razón social, og de står på ordren.
## Persondata
Persondatareglerne (Ley 1581) er indbygget: samtykke gemmes som bevis, dataudtræk og sletning kræver ny bekræftelse, og sletning anonymiserer kunden men bevarer ordrer og samtykke-bevis.
## Planlagt
E-fakturering ([DIAN](/integrationer/dian/)) og sager om klager (PQR) kommer i Colombia-sporet {{badge:plan}}.
> [!NOTE] Kilderne til de colombianske regler er delvist sekundære. Vi får dem gennemgået af en colombiansk jurist, før produktion.
---
# Danmark
(https://docs.webtrebol.dk/markeder/danmark/)
| Emne | Pakken |
|---|---|
| Valuta | DKK |
| Moms | 25 % |
| Virksomhed | CVR (kontrolcifre valideres) |
| Adresse | Postnummer; ingen regioner |
| Telefon | +45 |
| Helligdage | Danske helligdage |
| Fortrydelse | 14 dage, også før varen er leveret |
| Reklamation | 2 års reklamationsret |
| Kvittering | Dansk |
## Hvad der mangler før første rigtige shop
- Online betaling: [Stripe og MobilePay](/integrationer/stripe/) {{badge:wip}}.
- Juridiske tekster (vilkår, privatliv) som versionerede skabeloner.
- Frontend-krav, bl.a. garantimeddelelse og klageadgang. Se [Kravliste](/storefront/kravliste/) {{badge:plan}}.
Følg fremdriften på [Udvikling og opdateringer](site:/udvikling/).
---
# Markeder og markedspakker
(https://docs.webtrebol.dk/markeder/oversigt/)
Alle landeregler ligger samlet i en **markedspakke** pr. land. Kernen er landeuafhængig: penge gemmes som hele tal i mindste enhed, moms i basispoint, og adresse- og virksomhedsfelter er generiske.
## Hvad en pakke bestemmer
- Valuta og momssatser
- Adresseformat og regioner
- Virksomhedsidentifikation (CVR, NIT)
- Helligdage og fristberegning
- Fortrydelses- og reklamationsregler
- Kvitteringens sprog
## I dag
| Marked | Status |
|---|---|
| [Colombia](/markeder/colombia/) | {{badge:ok}} Første marked, i brug |
| [Danmark](/markeder/danmark/) | {{badge:wip}} Pakken er bygget; betaling og juridiske tekster er under udvikling |
| Andre EU-lande | {{badge:plan}} Arkitekturen er klar; en testpakke (EUR, 25 % moms, ingen regioner) beviser, at kernen er landeuafhængig |
En shop vælger sit marked ved oprettelsen.
---
# Ordliste
(https://docs.webtrebol.dk/ressourcer/ordliste/)
| Ord | Betydning |
|---|---|
| **Tenant** | En shop på platformen med egne, isolerede data |
| **Publishable key** | Offentlig nøgle, der identificerer en shop for en storefront |
| **Markedspakke** | Samlede landeregler: valuta, moms, adresser, frister |
| **Adapter** | Udskiftelig forbindelse til en ekstern tjeneste |
| **BYOK** | *Bring your own key* – shopejeren bruger egen konto og nøgler |
| **RLS** | *Row Level Security* – databasen sørger for isolering mellem shops |
| **Mindste enhed** | Valutaens mindste enhed; beløb gemmes som hele tal |
| **Basispoint** | Hundrededele af en procent; 25 % = 2500 |
| **Idempotens** | Samme anmodning to gange giver samme resultat, ikke to ordrer |
| **Webhook** | Et kald fra en tjeneste til en anden, når noget er sket |
| **Storefront** | Den kundevendte butik |
| **Backoffice** | Det administrative program til ejer og team |
| **DANE / DIVIPOLA** | Colombias officielle liste over departementer og kommuner |
| **IVA** | Colombias moms |
| **NIT / DV** | Colombiansk virksomhedsnummer og kontrolciffer |
| **CVR** | Dansk virksomhedsnummer |
| **PSE** | Colombiansk betaling direkte fra bankkonto |
| **Nequi** | Colombiansk mobilplatform til betaling |
| **Contra entrega** | Betaling ved levering |
| **DIAN** | Colombias skattemyndighed |
| **PQR** | Colombiansk klage- og henvendelsessag (*petición, queja, reclamo*) |
---
# AI-guide og prompt-skabelon
(https://docs.webtrebol.dk/storefront/ai-guide/)
Målet er, at en AI eller en udvikler kun med denne dokumentation kan bygge en storefront, der gennemfører hele flowet: browse, kurv, checkout, betaling og bekræftet ordre.
## Hvad der kommer
- **En kompakt guide** i stil med `llms.txt`: autentificering, kurv-token, checkout trin for trin, betalingsflowet, kvittering, marked og sprog, fejlkoder og hvad serveren allerede håndhæver.
- **Opskrifter** med kørende eksempler.
- **En prompt-skabelon**: «Byg min storefront ud fra disse docs».
- **Acceptprøve**: dokumentationen gives til en AI uden forudgående viden, som bygger en storefront mod en testshop. Fejler den, er det dokumentationen, der skal rettes.
## Det kan du bruge i dag
[`/llms.txt`](/llms.txt) og [`/llms-full.txt`](/llms-full.txt) indeholder hele den nuværende dokumentation som ren tekst. Giv dem til din AI sammen med [Købsflowet](/storefront/koebsflow/) og [Kravlisten](/storefront/kravliste/). Husk at markere sider med status Planlagt som ikke tilgængelige.
---
# Autentificering
(https://docs.webtrebol.dk/storefront/autentificering/)
Alt en storefront skal bruge findes under `/v1/store/*`. Hver forespørgsel identificerer shoppen med en **publishable key** i headeren `x-publishable-key`.
```http
GET /v1/store/shop
x-publishable-key: pk_test_DIN_NØGLE
```
> [!UDKAST] Rutenavne og header er hentet fra projektets egne noter og afstemmes mod OpenAPI-specen, når den findes ({{badge:plan}}). Brug siden som orientering, ikke som endelig reference.
## Publishable key
- Er offentlig og må ligge i frontend-koden.
- Fortæller kun, **hvilken shop** forespørgslen gælder.
- Skal kun kunne læse katalog, bruge kurv og gennemføre checkout. Den giver aldrig adgang til backoffice eller persondata.
I skabelonen sættes den som miljøvariablen `PUBLISHABLE_KEY` sammen med `API_URL`. Det er de to værdier, en ny storefront skal bruge.
## Hvad må aldrig ligge i en browser
- Nøgler til betalingsudbydere (secret keys).
- Tokens til backoffice (`/v1/admin/*`).
- Alt, der ikke er markeret som offentligt.
## Kunder
Kunder kan handle som gæster eller logge ind med e-mail og adgangskode eller Google. En kundesession er en separat, tilbagekaldelig token – den er ikke det samme som publishable key.
---
# Betaling
(https://docs.webtrebol.dk/storefront/betaling/)
Betalingen foregår altid hos udbyderen. Din storefront starter den og venter på resultatet.
## To måder at vise betalingen
| Måde | Hvordan |
|---|---|
| **Redirect** | Kunden sendes til udbyderens side (`checkoutUrl`) og kommer tilbage til din `returnUrl`. |
| **Indlejret** | Udbyderens widget vises i din checkout (`checkoutEmbed`). Falder tilbage til `checkoutUrl`, hvis widgetten ikke kan vises. |
Wompi understøtter begge dele i dag. Skabelonen indeholder en færdig Wompi-widget.
## Efter betalingen
Kunden lander på din returside, typisk med `?paid=1`. **Det er ikke en bekræftelse.** Frontenden skal hente ordrens status fra API'et (polling), indtil den er `confirmed`.
> [!WARNING] Marker aldrig en ordre som betalt i frontenden. Status ændres kun, når udbyderen har bekræftet betalingen over for platformen.
## Hvad platformen sørger for
- Bekræftelsen kommer via en verificeret webhook fra udbyderen; en periodisk afstemning fanger tabte webhooks.
- Beløbet kontrolleres mod ordren.
- En for sen, dobbelt eller forkert betaling markeres `refundRequired`, så den kan refunderes.
- Er betalingen afventende, holdes lageret i 120 minutter ekstra.
## Udbydere
- [Wompi](/integrationer/wompi/) – Colombia {{badge:ok}}
- [Betaling ved levering](/integrationer/betaling-ved-levering/) – Colombia {{badge:ok}}
- [Stripe](/integrationer/stripe/) – Danmark og EU {{badge:wip}}
## Tilladte retur-adresser
Platformen skal kun acceptere `returnUrl` til domæner, shopejeren har registreret. En sådan tilladelsesliste pr. shop er planlagt {{badge:plan}}; i dag tjekkes kun, at adressen er http(s).
---
# Conformance-test
(https://docs.webtrebol.dk/storefront/conformance-test/)
Testen er endnu ikke bygget. Her er, hvad den skal gøre.
## Formål
Give shopejeren et konkret bevis for, at en selvhostet storefront opfylder [kravlisten](/storefront/kravliste/) – før shoppen går live.
## Hvad den skal tjekke
- Findes betalingsknappen med korrekt tekst?
- Vises total inkl. moms og fragt, før kunden betaler?
- Findes link til fortrydelse, vilkår og klageadgang?
- Vises sælgeroplysninger i footer og checkout?
- Indlæses der eksterne scripts eller fonts på checkout?
## Sådan skal den bruges
Testen køres mod storefrontens adresse, og resultatet gemmes sammen med shopejerens erklæring i go-live-tjeklisten.
> [!NOTE] Når testen er bygget, flyttes siden til status Klar og får en vejledning til at køre den.
---
# Fortrydelse
(https://docs.webtrebol.dk/storefront/fortrydelse/)
Platformen har et selvbetjent fortrydelsesflow. Din frontend skal blot tilbyde det.
## Flowet
1. Kunden (også en gæst) åbner ordren via ordre-linket og vælger **Fortryd**.
2. Trin 1: en **forhåndsvisning** viser, hvad der fortrydes, og hvornår fristen udløber.
3. Trin 2: kunden **bekræfter**. Kunden får en bekræftelse.
4. Medarbejderen behandler sagen i backoffice: vare modtaget, refunderet eller afvist.
Delvis fortrydelse er understøttet, og enkelte produkter kan være undtaget.
## Frister
Fristen regnes fra levering og følger markedspakken:
| Marked | Frist |
|---|---|
| Danmark | 14 dage – også før varen er leveret |
| Colombia | 5 hverdage (med helligdagskalender) |
I Colombia regnes fristen fra levering: en medarbejder markerer ordren som sendt eller leveret i backoffice.
> [!WARNING] I en selvhostet frontend skal fortrydelsen kunne findes og bruges uden login i hele fristen. Se [Kravliste til frontend](/storefront/kravliste/).
---
# Købsflowet
(https://docs.webtrebol.dk/storefront/koebsflow/)
Flowet er det samme uanset frontend: **find varer → kurv → fragt → checkout → betaling → ordre**.
> [!UDKAST] Siden beskriver principperne og de felter, vi kender fra platformens specifikation. Præcise ruter og feltnavne afstemmes mod OpenAPI-specen ({{badge:plan}}).
## 1. Katalog
Hent produkter og varianter for shoppen. Varianter er valgbare muligheder som størrelse og farve. Priser leveres i mindste enhed (`...Minor`).
## 2. Kurv
Kurven er knyttet til en kurv-token, så gæster kan handle uden konto. Prisen er altid **live**: serveren regner moms og total, og tjekker lager. En gæstekurv kan flettes ind i kundens kurv ved login.
## 3. Fragt
Frontenden beder om mulige leveringsmåder for kurvens adresse (`POST /cart/shipping-options`). Fragtprisen sættes af serveren og indgår i totalen.
## 4. Betalingsmuligheder
Et endpoint (`payment-options`) fortæller, hvilke betalingsmetoder shoppen tilbyder (fx kort eller betaling ved levering).
## 5. Checkout
Checkout oprettes med:
- `acceptTerms: true` – kunden har accepteret vilkårene.
- `acceptedTotalMinor` – den total kunden så. Hvis serverens total er en anden, afvises købet i stedet for at kunden betaler et uventet beløb.
- en **idempotens-nøgle** – gentagne klik giver aldrig dobbelte ordrer.
Ved oprettelsen reserveres lageret (60 minutter) og ordren **frosses**: priser, moms, fragt og returpolitik ændres ikke bagefter.
## 6. Betaling og bekræftelse
Ordren står som `pending_payment`, indtil udbyderen bekræfter betalingen. Se [Betaling](/storefront/betaling/). Når bekræftelsen kommer, bliver ordren `confirmed`.
## 7. Ordre og kvittering
Kunden får et ordre-link (en token), hvor ordren kan ses, en kvittering hentes og en fortrydelse startes. Se [Kvittering](/storefront/kvittering/) og [Fortrydelse](/storefront/fortrydelse/).
## Fejl
Fejl returneres som afvisninger med kode (fx `unknown_municipality` ved en ugyldig kommune). En komplet fejlkodeliste kommer med OpenAPI-specen {{badge:plan}}.
---
# Kravliste til frontend
(https://docs.webtrebol.dk/storefront/kravliste/)
Platformen håndhæver reglerne i API'et. Men nogle krav ligger i **brugerfladen**, og dem skal din frontend selv opfylde. Her er listen, udledt af platformens lovkravsoversigt (K-numre).
> [!UDKAST] Listen er et arbejdsudkast og endnu ikke gennemgået af en jurist. Den er ikke juridisk rådgivning. Ordlyd og detaljer verificeres, før den bliver endelig.
| Krav | Hvad frontenden skal | Eksempel |
|---|---|---|
| **K1 Fortrydelse** | Tilbyde fortrydelsesfunktion uden login, i hele fristen | Et synligt «Fortryd aftale»-link på ordresiden og i ordremailen |
| **K4 Checkout** | Vise samlet pris inkl. moms og fragt før betaling; betalingsknap med tydelig betalingspligt; ingen forhåndsafkrydsede tilkøb; ingen nedtællingsure | Knap: «Ordre med betalingspligt» |
| **K5 Sælgeroplysninger** | Vise navn, adresse, e-mail og CVR/NIT i footer, checkout og ordremail | Hent oplysningerne fra shoppens opsætning |
| **K7 Ingen tredjepart** | Ingen eksterne scripts, fonts eller tracking på checkout | Selvhostede fonts; ingen reklamepixels |
| **K8 Cookies** | Kun nødvendige cookies og lokal lagring; ingen pixels uden samtykke | Beskriv cookies i cookiepolitikken |
| **K16 Klage** | Vise klageadgang | Danmark: Center for Klageløsning. Colombia: SIC og PQR |
| **K17 Garanti** | Vise den lovpligtige garantimeddelelse (DK) | Fast tekst, ordlyd verificeres |
| **K26 Tilgængelighed** | Opfylde WCAG 2.1 AA | Kontrast, tastaturnavigation, labels |
## Eksempel: betalingsknap
```html
```
## Erklæring og test
Når en dansk shop med egen storefront går live, skal shopejeren i go-live-tjeklisten bekræfte, at kravene er opfyldt, og have kørt [conformance-testen](/storefront/conformance-test/) mod sin storefront. Skabelonens checkout er allerede bygget til at opfylde kravene og er det sikre udgangspunkt.
---
# Kvittering og ordreside
(https://docs.webtrebol.dk/storefront/kvittering/)
Efter købet får kunden et ordre-link med en token. Via den kan frontenden hente ordren og en kvittering.
## Kvittering som PDF
`GET /orders/:token/receipt.pdf` returnerer en PDF på markedets sprog. Kvitteringen er frosset ved ordreoprettelsen og er **ikke en faktura**.
> [!NOTE] Et almindeligt link (``) direkte til API'et virker ikke, fordi en browser ikke kan vedhæfte headeren `x-publishable-key`. Lad din egen server hente PDF'en og sende den videre. Skabelonen gør det med en route handler (`app/api/receipt/[token]/route.ts`).
## Ordrebekræftelse på e-mail
Platformen sender ordrebekræftelsen, uanset hvilken frontend der bruges. Afsendelsen er bygget, men slås til sammen med mailopsætningen {{badge:wip}}. Se [E-mail](/integrationer/mail/).
---
# Markeder og sprog
(https://docs.webtrebol.dk/storefront/markeder-og-sprog/)
En shop hører til ét marked. Storefronten skal ikke gætte reglerne – den spørger API'et.
## Shoppens opsætning
`GET /v1/store/shop` returnerer de offentlige oplysninger om shoppen: marked, valuta og sælgeroplysninger. Brug dem til at vise rigtige tekster, priser og felter.
## Adressefelter følger markedet
Checkout-formularen tilpasser sig markedet. I Danmark er der postnummer og ingen regioner. I Colombia vælges *departamento* og *municipio*.
| Endpoint | Formål |
|---|---|
| `GET /v1/store/regions` | Liste over regioner (Colombia: 33 departementer). Tom for Danmark. |
| `GET /v1/store/regions/:code/localities` | Kommuner i en region (fx 125 i Antioquia). Ukendt kode giver 404. |
En ugyldig kommunekode afvises af checkout med `unknown_municipality`.
## Sprog
Tekster og oversættelser bør ligge som data pr. marked, så en frontend kan skifte sprog uden at ændre koden. Skabelonen bruger en `locales/`-mappe.
> [!UDKAST] Endepunkter og felter afstemmes mod OpenAPI-specen {{badge:plan}}.
---
# Ansvar og designfrihed
(https://docs.webtrebol.dk/storefront/oversigt/)
Du er fri til at bygge storefronten, som du vil: vores skabelon, din egen kode eller en AI-bygget frontend. Det er en bevidst arbejdsdeling.
## Det ligger hos platformen
- Pris, moms, lager, fragt og totaler – beregnes og valideres i API'et.
- Ordren: oprettes idempotent, lager reserveres, og ordren frosses.
- Betalingsstatus: bekræftes kun af betalingsudbyderen.
- Fortrydelsesfrister, ordrebekræftelse og kvittering.
- Backoffice, database og juridiske tekster.
## Det ligger hos dig
- Design, sider og tekster.
- Hosting af frontenden på dit eget domæne.
- At **din checkout lever op til kravene til brugerfladen** – knaptekster, sælgeroplysninger, fortrydelseslink m.m. Platformen kan ikke tvinge en fri frontend til det. Se [Kravliste til frontend](/storefront/kravliste/).
## Betaling
Checkout kører på dit domæne, men betalingen foregår i udbyderens eget felt eller på udbyderens side (fx Wompi-widget eller Stripe Payment Element). Kortdata rører aldrig dig eller os.
> [!WARNING] En selvhostet frontend er shopejerens ansvar. Platformen er ikke ansvarlig for betalingsflowet eller lovkrav til brugerfladen i en frontend, vi ikke har bygget. Det er ikke juridisk rådgivning.
## Tre veje
1. **Brug skabelonen** (`apps/storefront`, Next.js). Den er et fuldt fungerende udgangspunkt.
2. **Byg selv** mod API'et. Start med [Autentificering](/storefront/autentificering/) og [Købsflowet](/storefront/koebsflow/).
3. **Lad en AI bygge den.** Se [AI-guide](/storefront/ai-guide/) {{badge:plan}}.
---
# Publicér selv
(https://docs.webtrebol.dk/storefront/publicer-selv/)
Alle storefronts hostes af shopejeren selv. Platformen hoster ingen kunders storefront.
## Det skal du bruge
Skabelonen kræver to værdier:
```bash
PUBLISHABLE_KEY=pk_test_DIN_NØGLE
API_URL=https://api.webtrebol.dk
```
Derefter kan den deployes til en vilkårlig hosting – fx Vercel, Netlify eller Cloudflare.
## Det der bliver tilføjet
- En vejledning pr. hostingtjeneste (domæne, miljøvariabler).
- Registrering af din storefronts domæner i backoffice, så kun de må kalde API'et og bruges som retur-adresse efter betaling (CORS og `returnUrl`-tilladelsesliste).
- En «Deploy»-knap, når skabelonen er udgivet som open source.
> [!NOTE] Indtil videre bruger skabelonen en server-side proxy til API'et. Det gør, at den ikke behøver CORS. Bygger du en ren browser-app, skal du vente på tilladelseslisten.
---
# API-oversigt
(https://docs.webtrebol.dk/udvikler/api-oversigt/)
API'et er REST over HTTPS. Alle rutenavne starter med en version.
## Områder
| Område | Bruges af | Adgang |
|---|---|---|
| `/v1/store/*` | Storefronts | Publishable key (`x-publishable-key`) |
| `/v1/admin/*` | Backoffice | Medarbejder-token |
| `/v1/platform/*` | Oprettelse af shops og platformens opsætning | Offentlig eller privilegeret, afhængigt af ruten |
Kunders ordre-links og kvitteringer bruger en ordre-token. Et sundhedstjek findes på `/health`.
## Principper
- **Versionering:** `/v1` ændres kun additivt. Nye felter og ruter kan komme; eksisterende ændrer ikke betydning.
- **Penge** er hele tal i mindste enhed (`...Minor`); moms er i basispoint.
- **Idempotens:** checkout kræver en idempotens-nøgle.
- **Serveren er sandheden:** totaler, lager og betalingsstatus beregnes af API'et.
- **Fejl** returneres som afvisninger med en kode.
## Reference
> [!UDKAST] Der findes endnu ingen komplet OpenAPI-spec. Den er planlagt sammen med en typet SDK {{badge:plan}}. Indtil da er siderne under [Byg en storefront](/storefront/oversigt/) den bedste beskrivelse af flowet.
## Eksempler fra platformen
| Rute | Formål |
|---|---|
| `GET /v1/store/shop` | Shoppens offentlige oplysninger |
| `GET /v1/store/regions` | Regioner for markedet |
| `GET /v1/store/regions/:code/localities` | Kommuner i en region |
| `POST /cart/shipping-options` | Leveringsmuligheder for en kurv |
| `GET /orders/:token/receipt.pdf` | Kvittering som PDF |
| `POST /auth/google`, `GET /auth/config` | Google-login til kunder |
| `GET /v1/platform/markets` | Markeder, en ny shop kan vælge |
---
# Sikkerhed
(https://docs.webtrebol.dk/udvikler/sikkerhed/)
## Data
- Hver shops data er isoleret i databasen (*Row Level Security*).
- Betalingsudbyderes nøgler gemmes krypteret og returneres aldrig i admin-API'et.
- Persondata kan eksporteres og slettes efter reglerne; regnskabsdata bevares.
## Betalinger
- Kortdata indtastes kun i udbyderens eget felt eller side. Vi designer efter det laveste PCI-scope (SAQ A).
- En betaling bekræftes kun af udbyderens verificerede webhook eller afstemning.
## Login
- Adgangskoder hashes med scrypt, og der kræves en stærk adgangskode.
- Kundesessioner er hashede, tilbagekaldelige tokens (30 dages glidende og 90 dages absolut levetid).
- Begrænsning af forsøg pr. konto og IP-adresse; ingen afsløring af, om en konto findes.
- En append-only sikkerhedslog.
## Frontend
- Hold nøgler til udbydere og backoffice-tokens ude af browseren. Se [Autentificering](/storefront/autentificering/).
- Indholdssikkerhedspolitik (CSP) uden tredjepartsscripts på checkout er under indførelse {{badge:wip}}.
---
# Hændelser, webhooks og API-nøgler
(https://docs.webtrebol.dk/udvikler/webhooks/)
Du skal kunne udvide en shop uden at røre kernen – også med kode i et helt andet sprog.
## Planen
- **Hændelser** gemmes i en tabel, der kun kan tilføjes til: fx `order.created`, `order.paid`, `order.shipped` og `withdrawal.requested`.
- **Udgående webhooks** pr. shop: signerede kald med nye forsøg og en kø for mislykkede leveringer.
- **API-nøgler** pr. shop med scopes (kun læsning, ordrer, produkter), som kan roteres og gemmes hashet.
## Eksempel
En Blazor-app lytter på `order.paid` og kalder API'et for at oprette en forsendelse eller bogføre. Alt sker over HTTP – kundens kode køres aldrig i platformens proces.
> [!NOTE] Kald, som platformen foretager synkront under selve købet, er ikke en del af planen i første omgang.