Hoppa till innehållet
Utvecklare

Webbshopsintegration, från varukorg till retur.

Samma API som kassorna använder, från webbshopens backend: koppla kundkonton till medlemmar, prissätt varukorgen med rabattkoder och frakt, håll rabatterna reserverade medan en onlinebetalning slutförs och hantera returen veckor senare.

Läs den tillsammans med integrationsguiden för kassasystem: anropen är desamma, och den här guiden tar upp var en webbshop gör dem annorlunda. Referensen gäller för varje fält. Exemplen är förkortade och beloppen är bara exempel.

Innan du börjar

Anropa Custas från din backend, aldrig från webbläsaren

En API-nyckel kan lösa in presentkort och läsa medlemsdata, så den får aldrig hamna i en webbläsare. API:et tar ändå inte emot anrop från andra webbplatsers sidor: dess CORS-policy tillåter bara Custas-portalen. Din butiksfront pratar med din backend, och din backend pratar med Custas.

En nyckel med webbshopens behörigheter

Behörighet Används till
members:read Slå upp medlemmar, poäng, stämpelkort och Wallet-kort
members:write Skapa medlemmar, registrera samtycke, varukorgshändelser (§8)
carts:evaluate Prissättning
redemptions:write Reservera, slutföra, släppa, returer, återföring
redemptions:read Hitta köpet för en order; orderhistorik i Mitt konto
giftcards:read, giftcards:write Presentkortssaldo; sälja, mejla och återbetala presentkort (bara om du tar emot eller säljer dem)
settings:read Identitetsregler och samtyckestexter
messaging:write (valfri) Mejl för dubbel opt-in, mejla ett presentkort som sålts

Bygg mot en cust_test_…-nyckel: testmiljön är helt separat från live. Nycklarna har en anropsgräns per minut som beror på planen (Starter 60, Growth 600, Enterprise 6 000 anrop), vilket spelar roll för prissättningen (§3).

Samma konventioner som i en kassa

  • Belopp anges som heltal i minsta valutaenhet (19900 är 199,00 kr), priser är inklusive moms om inte handlaren använder nettopriser, och den momsfördelning som Custas returnerar är den du ska visa och fakturera.
  • Idempotency-Key krävs när du reserverar, slutför, släpper, återför och gör returer, och när du utfärdar och mejlar presentkort. Härled den från din order, till exempel WEB-100231-commit, så att ett nytt försök, en dubbelklickad knapp och en betalningswebhook som kommer samtidigt som omdirigeringen alla skickar samma nyckel.
  • Varje varukorg anger "channel": "online" och ett stabilt storeId för webbshopen, till exempel "web". Kampanjer kan begränsas till kanaler och butiker, så kom överens med handlaren om id:t: ett erbjudande som bara gäller fysiska butiker gäller då, som det ska, inte online.

1. Kundkonton och medlemmar

En kassa känner igen en medlem på ett kort eller ett telefonnummer som hen visar upp. En webbshop känner sina kunder genom deras kundkonto, och det är inloggningen som avgör vem de är. Koppla ihop de två en gång och använd sedan medlemmens id.

Koppla en inloggad kund till rätt medlem

POST /v1/members/lookup

{ "keyType": "email", "value": "anna.svensson@example.com" }

# → 200: medlemmen, med "id". Spara det på kundkontot.
# → 404: inte medlem än. Erbjud medlemskap (§2).
  • Slå bara upp den verifierade e-postadressen för ett inloggat konto: en adress som din webbshop har bekräftat att kunden har kontroll över, till exempel med en bekräftelselänk när kontot skapades.
  • Spara medlemmens id på kundkontot och använd det överallt efter det. Om kunden byter e-postadress i din webbshop håller kopplingen ändå.
  • Be handlaren göra email till en unik identifierare i identitetsreglerna (GET /v1/tenant/identity-rules visar dem). Om den inte är unik kan två medlemmar dela adress, och då returnerar en uppslagning en av dem.

Låt aldrig en anonym besökare utlösa en uppslagning. Uppslagningen returnerar medlemmens poäng, nivå och köpbelopp, och Custas kan inte avgöra åt din webbshop att den som skriver in en e-postadress också äger den. Ett fält i gästkassan för ”din medlemsadress” skulle låta vem som helst kolla vem som är medlem, se saldot och använda poängen. Gäster handlar som gäster; medlemsförmåner kräver ett inloggat konto.

Gäster

Prissätt en gästs varukorg utan member. Publika kampanjer och rabattkoder gäller fortfarande; erbjudanden för medlemmar och nivåer gör det inte. Efter ordern kan du erbjuda kunden att skapa ett konto och gå med, så att nästa order ger poäng.

2. Registrering och samtycke

Skapa medlemmen när en kund går med i lojalitetsprogrammet: när kontot skapas, eller med en kryssruta ”gå med och tjäna poäng” i kassan. Även här bara för en e-postadress som din webbshop har verifierat.

POST /v1/members

{
  "displayName": "Anna Svensson",
  "locale": "sv-SE",
  "country": "SE",
  "externalRef": "shop-customer-58213",       # ditt eget kund-id, unikt per handlare
  "identities": [
    { "keyType": "email", "value": "anna.svensson@example.com", "isPrimary": true }
  ],
  "attributes": { "signupChannel": "web" }
}
  • Skicka alla identifierartyper som identitetsreglerna markerar som obligatoriska. Ett formulär som bara frågar efter e-post misslyckas med 422 om handlaren kräver telefonnummer.
  • 409 identity_conflict: e-postadressen tillhör redan en medlem, kanske någon som gick med i en butik. Slå upp hen och koppla den medlemmen; skapa ingen ny.
  • Det här anropet tar ingen Idempotency-Key. Om svaret försvinner är ett nytt försök ändå säkert: det andra försöket svarar 409 (e-postadressen eller ditt externalRef är upptaget), och då slår du upp medlemmen.

Marknadsföringssamtycke: en egen fråga, inte förkryssad

Att gå med i programmet är inte samtycke till marknadsföring. Fråga med en egen kryssruta, inte förkryssad, som visar den exakta texten i handlarens aktiva samtyckestext (GET /v1/consent-wordings). Registrera bara ett ja:

PUT /v1/members/{id}/consents/email/marketing

{
  "state": "granted",
  "source": "api",
  "sourceDetail": "webshop sign-up form, shop.example.com",
  "wordingId": "0199a4f1-…",
  "actor": "customer:shop-customer-58213"
}
  • source är api för en webbshop. Beskriv var det skedde i sourceDetail; det är en del av bevisningen.
  • Custas registrerar anropets IP-adress och user agent, som här är din servers, inte kundens. Vill du spara kundens egen IP-adress i din dokumentation får du lagra den själv.
  • Dubbel opt-in är starkare bevis online, där vem som helst kan skriva in vems adress som helst. Skicka den i stället för att registrera samtycket direkt: POST /v1/members/{id}/consent-confirmations med channel, purpose, templateKey och wordingId (kräver messaging:write). Kunden bekräftar på en sida hos Custas, och länken fungerar i sju dagar.
  • Om handlaren har satt en lägsta ålder för marknadsföring och medlemmen enligt sitt födelsedatum är yngre än så, svarar ett samtycke 422 med reason: "below_marketing_min_age". Själva medlemskapet har ingen åldersgräns.
  • Erbjud återkallelse i kontoinställningarna också ("state": "withdrawn"). Den nekas aldrig.

3. Prissätt varukorgen

Utvärdera när varukorgssidan visas, när varukorgen eller en rabattkod ändras, och i varje steg i kassan som ändrar frakt eller betalmedel. Anropet läser bara och reserverar ingenting.

POST /v1/carts/evaluate

{
  "currency": "SEK",
  "channel": "online",
  "storeId": "web",
  "country": "SE",
  "member": { "memberId": "0199a4f0-1c2d-7e3f-8a4b-5c6d7e8f9a0b" },
  "codes": ["SUMMER20"],
  "lines": [
    { "id": "item-8812", "sku": "TSH-SPORT-2PK", "quantity": 2,
      "unitPriceMinor": 19900, "taxRateBp": 2500,
      "categories": ["clothing"], "brands": ["Acme"], "description": "Sport T-shirt (2-pack)" }
  ],
  "shipping": { "methodId": "postnord-home", "amountMinor": 4900, "taxRateBp": 2500 }
}
  • Rad-id:n är stabila under hela varukorgens livstid: använd ditt eget id för varukorgsraden, inte radens position. Skicka alla attribut som kampanjer kan rikta sig mot (categories, brands, collections, tags, isSale, productId, variantId), som i kassasystemguiden.
  • Frakt skickas i shipping, med egen momssats, inte som en rad. Kampanjer för fri frakt och fraktrabatt verkar på den, och prisberäkningen returnerar shippingMinor och shippingDiscountMinor.
  • excludeFromDiscounts: true för allt som webbshopen aldrig rabatterar; isGiftCard: true för presentkort som säljs (§10).
  • Tänk på anropsgränsen. Utvärdera vid händelser, inte vid varje rendering, och återanvänd den senaste prisberäkningen så länge varukorgen inte har ändrats. Med Starters 60 anrop per minut tar det snabbt slut om du räknar om vid varje sidvisning.

Fältet för rabattkod

Lägg det kunden skrev i codes. Stora och små bokstäver, mellanslag, bindestreck och förväxlingsbara I/L/O förlåts. En kod som inte gäller får aldrig anropet att misslyckas: resten av varukorgen prissätts, och koden kommer tillbaka i rejectedCodes med en orsak som du kan förklara under fältet.

reason Säg till kunden
not_found Den koden finns inte
not_started, expired Den koden gäller inte än / inte längre
exhausted, budget_exhausted Erbjudandet är slut
member_limit_reached Du har redan använt koden så många gånger som det går
assigned_to_other_member Det här är en personlig kod för någon annan
no_member Logga in för att använda den här medlemskoden
wrong_channel, wrong_store Den här koden gäller i butik
below_min_subtotal Handla för lite mer för att kunna använda koden
combination_conflict Den här koden kan inte kombineras med ditt andra erbjudande
allt annat Den koden kan inte användas på den här ordern

Nya orsaker kan tillkomma, så ha alltid med den sista raden. Vill du ta reda på varför ett automatiskt erbjudande inte gällde kan du lägga till ?explain=true medan du felsöker.

Visa prisberäkningens priser per rad, appliedPromotions och vatBreakdown som de är, och spara quoteHash till när ordern läggs.

Referens: utvärdera en varukorg

4. Presentkort och poäng som betalning

Båda är betalmedel i samma varukorg, precis som i en kassa (kassasystemguiden §4): de minskar amountDueMinor, och resten tar du betalt för via din betalleverantör.

"tenders": [
  { "type": "gift_card", "code": "GC-7Q4M-XK2P-9TND" },
  { "type": "points", "points": 500 }
]
  • Poäng bara för en inloggad medlem. Visa vad de är värda med GET /v1/members/{id}/points (redeemablePoints, redeemableMinor). Poäng kan inte användas för att betala presentkort som köps.
  • Presentkort har ingen PIN-kod: koden räcker för att använda saldot. Skydda presentkortsfältet mot botar på samma sätt som din inloggning (en CAPTCHA och en gräns per besökare), och visa aldrig saldot för en kod för en besökare som inte har lagt den på sin egen order.
  • Ett avvisat betalmedel anger orsaken i reason (not_found, expired, no_balance, …). Resten av ordern kan fortfarande betalas.

5. Lägg order och betala

Skillnaden mot en kassa: en onlinebetalning tar tid och bekräftas asynkront, ofta med en webhook från din betalleverantör, flera minuter efter att kunden lämnade kassan. Custas håller rabatterna, kodanvändningarna, presentkortsbeloppen och poängen reserverade under tiden, så att ingen annan kan ta dem.

Onlinekassa: webbshopen utvärderar, reserverar så länge betalningen kan ta, startar en betalsession som går ut först och slutför när betalleverantören bekräftar. En misslyckad eller avbruten betalning släpper reservationen. Kund Betalleverantör Butiksbackend Custas Lägg order POST /v1/carts/evaluate quoteHash POST /v1/redemptions 201 held session, går ut först betalar (3-D Secure…) betalning bekräftad POST …/{id}/commit 200 committed order bekräftad Misslyckad? POST …/{id}/release

Reservera när kunden trycker på ”Lägg order”

Utvärdera en sista gång med den slutliga varukorgen och reservera sedan mot den prisberäkningen:

POST /v1/redemptions
Idempotency-Key: WEB-100231-1-reserve

{
  "cart": { …exakt den varukorg du nyss utvärderade… },
  "quoteHash": "7f3a9c…e21b",
  "externalRef": "WEB-100231-1",
  "ttlSeconds": 1800
}
  • Varje 409 innehåller en ny quote: priset har ändrats sedan kunden senast såg det (en kod tog slut, ett erbjudande upphörde, handlaren ändrade en kampanj). Visa den nya totalsumman, låt kunden bekräfta och reservera igen på quote.quoteHash med en ny nyckel. Det är samma enda väg som i en kassa (kassasystemguiden §5).
  • Spara reservationens id på ordern och debitera dess amountDueMinor, där presentkort och poäng redan är avdragna.
  • En order från en gäst utan rabatt, kod, presentkort eller poäng har inget att reservera, och att reservera den ger svaret 409 conflict. Hoppa över Custas för sådana ordrar.

externalRef: ditt ordernummer plus ett försöksnummer

externalRef är unikt per handlare, inklusive reservationer som har släppts eller löpt ut. Om kundens första betalning misslyckas och hen försöker igen behöver ordern en ny reservation, och den kan inte återanvända samma referens. Använd ordernumret med en försöksräknare (WEB-100231-1, WEB-100231-2, …). För att hitta köpet senare söker du på referensen för det försök som slutfördes, och den har du sparat på ordern.

ttlSeconds: längre än betalningen kan ta

Reservationen gäller i ttlSeconds: 900 (15 minuter) som standard och högst 3600 (en timme). Den kan inte förlängas. Välj ett värde som täcker den längsta tid din betalsida kan vara öppen, och låt betalsessionen gå ut innan reservationen gör det. De flesta betalleverantörer låter dig ställa in sessionens livslängd. Då kan en kund aldrig betala efter att rabatterna hen blev lovad har gått tillbaka till poolen.

Slutför (commit) när betalleverantören bekräftar

POST /v1/redemptions/{id}/commit
Idempotency-Key: WEB-100231-1-commit

{
  "payments": [
    { "method": "invoice", "label": "Klarna", "reference": "kl-7f2a91c0",
      "amountMinor": 33740 }
  ]
}
  • Slutför från det ställe där du får veta att betalningen lyckades: omdirigeringen tillbaka till webbshopen, leverantörens webhook eller båda. Båda skickar samma Idempotency-Key, så den som kommer sist får samma svar som den första, och köpet slutförs bara en gång.
  • payments måste summera till reservationens amountDueMinor. method är card, swish, invoice, voucher eller other. Ange leverantören i label ("Klarna", "PayPal") och dess transaktions-id i reference. För kort skickar du bara det maskerade numret om du har det: ett fullständigt kortnummer nekas.
  • receipt är valfritt och byggt för kassor: dess number är ett löpnummer för kvitton i form av ett heltal. Utelämna det om inte handlaren skickar digitala kvitton till Kivra; ditt ordernummer finns redan i externalRef.
  • Slutför även när inget rabatterades, för en inloggad medlem. Det är så hen tjänar poäng och stämplar, och så räknas ordern in i hens historik.

Släpp när betalningen misslyckas eller avbryts

POST /v1/redemptions/{id}/release
Idempotency-Key: WEB-100231-1-release

{ "reason": "cancelled" }

Släpp så fort du vet: när leverantören rapporterar ett fel eller när betalsessionen går ut. Då går en kods sista användning direkt till nästa kund, i stället för först när reservationen löper ut.

Referens: inlösen (redemptions)

6. När betalningen bekräftas efter att reservationen löpt ut

Om betalsessionen trots allt varade längre än reservationen svarar commit-anropet 409 reservation_not_held, och kunden har betalat. Custas kan inte slutföra ett köp vars rabatter har gått tillbaka till poolen, så:

  1. Utvärdera orderns varukorg igen och reservera den under nästa försöks referens (WEB-100231-2).
  2. Om det nya amountDueMinor är lika med det kunden betalade slutför du direkt. Inget går förlorat.
  3. Om det är högre (en kod tog slut under tiden) släpper du reservationen. Leverera ordern till det pris kunden betalade, vilket är en sak mellan dig och kunden, och ge kunden poäng för ordern utan rabatten: POST /v1/members/{id}/points/earn med amountMinor och det rena ordernumret som externalRef (WEB-100231). Anropet är idempotent på den referensen, och den får inte vara en som en reservation redan har använt.

Prenumerera på redemption.released. En leverans med reason: "ttl" för en order som du fortfarande ser som öppen är din tidiga varning om att reservationen har löpt ut.

7. Mitt konto

För en inloggad medlem fungerar de här med webbshopens nyckel:

GET /v1/members/{id}/points          # saldo, värde, nivå, poäng som snart går ut
GET /v1/members/{id}/stamp-cards     # stämplar och intjänade belöningskoder
GET /v1/members/{id}/wallet/google   # → { "saveUrl" } för en knapp ”Lägg till i Google Wallet”
GET /v1/members/{id}/wallet/apple    # → .pkpass för ”Lägg till i Apple Wallet”
GET /v1/redemptions?memberId={id}    # köp med Custas-förmåner, nyaste först
  • Belöningskoder från stämpelkort med status: "active" är medlemmens att använda: visa dem på kontot, så gäller de när de skrivs in i kodfältet.
  • Poäng som tjänats in på en order kan användas direkt; det finns ingen väntetid.
  • Medlemmens personliga erbjudanden är inte tillgängliga för en API-nyckel. De visas i Custas medlemsapp, så länka till den från kontosidan.

8. Övergivna varukorgar

För att skicka ”du har glömt något i varukorgen” berättar du för Custas vad en inloggad medlem har i sin varukorg, från din backend, varje gång den ändras. Handlaren ställer in en automation för kvarlämnad varukorg i portalen (till exempel 4 timmar senare, med en rabattkod), och Custas skickar den, med samtycket kontrollerat som för alla marknadsföringsutskick. Inget skript körs i webbläsaren, och inget registreras för besökare som inte har loggat in.

POST /v1/webshop-carts/events

{
  "type": "cart_updated",                      # eller checkout_started, cart_abandoned,
                                               #    checkout_completed, cart_cleared
  "cartId": "c-7f3a91",                        # ditt varukorgs-id
  "member": { "memberId": "0190f0f0-…" },      # eller { "keyType": "email", "value": … }
  "currency": "SEK",
  "lines": [
    { "sku": "W-DIVER-300", "name": "Diver 300", "quantity": 1, "unitPriceMinor": 489500,
      "imageUrl": "https://shop.example.se/img/diver-300.jpg" }
  ],
  "recoveryUrl": "https://shop.example.se/cart"
}

# → 200: { "cart": { …, "status": "open", "ignored": false } }
  • Skicka hela varukorgen vid varje cart_updated och checkout_started; den ersätter det som fanns. Det går bra att skicka vid varje ändring. Påminnelsen räknas från den senaste.
  • Skicka checkout_completed när ordern läggs och cart_cleared när varukorgen töms. Att slutföra ett köp för medlemmen (§5) stoppar också påminnelsen, så ett missat checkout_completed leder inte till en påminnelse om något hen redan har köpt.
  • Varje varukorg får en påminnelse. Om samma cartId används igen efter att varukorgen stängts (slutförd, tömd eller följd av ett köp) börjar den om och kan få en ny påminnelse. Långlivade varukorgar för inloggade kunder fungerar som de är.
  • Skickar du från en kö? Ange occurredAt. En händelse som är äldre än varukorgens senaste aktivitet kommer tillbaka med "ignored": true och ändrar ingenting, så ett sent cart_updated kan inte öppna en avslutad varukorg igen.
  • recoveryUrl är länken i meddelandet ({{cart.url}}): din egen https-sida som återställer varukorgen när kunden har loggat in. Mallen kan också skriva ut {{cart.items}}, {{cart.value}} och {{cart.imageUrl}}.
  • Varukorgar är personuppgifter: Custas sparar dem i 90 dagar efter senaste aktivitet, raderar dem tillsammans med medlemmen och tar med dem i medlemmens registerutdrag.

9. Returer

Hitta köpet med referensen du sparade på ordern:

GET /v1/redemptions?externalRef=WEB-100231-1

Några varor kommer tillbaka

POST /v1/redemptions/{id}/returns
Idempotency-Key: WEB-100231-return-1

{
  "lines": [{ "lineId": "item-8812", "quantity": 1 }],
  "reason": "wrong size"
}
  • Varje enhet återbetalas med vad den kostade när den såldes, rabatten inräknad. Läs beloppet, med moms, från den nya posten i svarets returns och återbetala exakt det via din betalleverantör. Räkna inte ut det själv.
  • Poängen som varorna gav dras tillbaka, så långt medlemmen fortfarande har kvar dem.
  • Frakt är ingen rad, så den kan inte returneras på det här sättet. Om din policy är att återbetala frakt gör du det via din betalleverantör; det ändrar ingenting i Custas.
  • En delretur ger inte tillbaka koden eller erbjudandet, och inte heller presentkortet eller poängen som betalade. För att sätta tillbaka pengar på ett presentkort använder du POST /v1/gift-cards/{id}/refund med beloppet och ett externalRef.
  • Custas tillämpar ingen returperiod. Din webbshops returpolicy avgör vad som godtas.

Hela ordern avbryts eller returneras

POST /v1/redemptions/{id}/reverse
Idempotency-Key: WEB-100231-reverse

{ "reason": "order cancelled" }

Det här ångrar allt: kodanvändningar och erbjudandebudgetar kommer tillbaka, och presentkort och poäng som betalade återbetalas till kortet och medlemmen. Efter delreturer tas bara det som återstår tillbaka, och en andra återföring ändrar ingenting.

10. Sälja presentkort

  1. Lägg presentkortet i varukorgen som en rad med "isGiftCard": true. Inget rabatterar det, och det kan inte betalas med poäng. Utvärdera, reservera, betala och slutför som vanligt.
  2. Utfärda kortet när köpet har slutförts. Härled nyckeln från orderraden, så att ett nytt försök returnerar samma kort i stället för att ladda ett kort till:
    POST /v1/gift-cards
    Idempotency-Key: WEB-100231-gc-item-8813
    
    { "amountMinor": 50000, "memberId": "0199a4f0-…", "note": "order WEB-100231" }
  3. Mejla det till mottagaren. Mallen måste innehålla koden; handlaren ställer in den i portalen.
    POST /v1/gift-cards/{id}/deliveries
    Idempotency-Key: WEB-100231-gc-item-8813-send
    
    { "templateKey": "gift-card", "email": "erik@example.com",
      "message": "Happy birthday!", "locale": "sv-SE" }
  • Mejlutskick kräver messaging:write. Att skicka till en inskriven adress kräver också members:reveal, om inte samma nyckel utfärdade kortet under de senaste 30 minuterna, vilket är det normala direkt efter köpet.
  • Det finns inget schemalagt utskick. För ”leverera på hennes födelsedag” sparar du kortets id och anropar deliveries på dagen.
  • Det utfärdade kortets code finns bara i svaret när kortet utfärdas. Spara eller logga den inte, utöver att lämna den vidare till leveransen.

11. Webhooks

Orderflödet fungerar utan webhooks: svaret på varje steg kommer tillbaka i anropet. Prenumerera för att hålla webbshopen i takt med det som händer på annat håll (kräver Growth-planen eller högre):

Händelse Varför en webbshop vill ha den
redemption.released En reservation löpte ut (reason: "ttl") på en order som du tror är öppen
member.merged Peka om kundkontot från den sammanslagna medlemmens id till den som behölls
member.deleted Medlemmen har raderats: ta bort kopplingen och radera det du kopierat
consent.changed Håll ditt nyhetsbrevsverktyg i takt när samtycket ändras i en butik
tier.changed Flytta kunden till en annan kundgrupp i webbshopen
Webhookguiden: signaturer, nya försök, dubbletter

12. Fel

Svar Var Webbshopen
404 not_found Uppslagning Erbjuder medlemskap
404 med mergedInto Hämta medlem Sparar det nya id:t på kundkontot
409 identity_conflict Skapa medlem Slår upp samma e-postadress och kopplar den medlemmen
409 med en quote Reservera Visar den nya totalsumman; reserverar igen på quote.quoteHash
409 conflict Reservera externalRef är redan använt (använd nästa försök), eller så har en anonym order inget att reservera (hoppa över Custas)
409 reservation_not_held Slutför Följer §6
409 idempotency_request_in_progress Alla anrop med nyckel Väntar retryAfter och gör ett nytt försök med samma nyckel
422 med below_marketing_min_age Samtycke Förklarar att marknadsföring inte är tillgänglig under den åldern
422 validation_failed Alla errors[].field anger vilket fält som ska rättas
429 rate_limited Alla Väntar Retry-After; utvärderar mer sällan
5xx, timeout Alla Gör nya försök med samma nyckel för anrop med nyckel. Om Custas inte går att nå vid ”Lägg order”: sälj till ordinarie pris, utan koder och lojalitetsförmåner, i stället för att blockera kassan

13. Checklista

  • API-nyckeln finns i backend; butiksfronten anropar aldrig Custas
  • Kundkonton sparar medlemmens id; uppslagning bara för verifierade e-postadresser hos inloggade kunder
  • Gäster prissätts utan medlem; ingen anonym uppslagning någonstans
  • Registreringen skickar handlarens obligatoriska identifierare; en konflikt leder till koppling
  • Marknadsföringssamtycke efterfrågas separat, inte förkryssat, med textens id
  • Varje varukorg har channel: "online" och det överenskomna storeId
  • Frakt skickas som shipping, inte som en rad
  • Avvisade koder förklaras under kodfältet, med ett reservmeddelande
  • Presentkortsfältet är skyddat mot gissning
  • Reservera vid ”Lägg order”, med en enda 409-väg som visar den nya totalsumman
  • externalRef innehåller ett försöksnummer
  • Betalsessionen går ut före reservationen
  • Slutför från omdirigeringen och leverantörens webhook med samma nyckel
  • Släpp vid misslyckad eller avbruten betalning
  • En plan för en betalning som bekräftas efter reservationen
  • Varukorgshändelser skickas för inloggade medlemmar, med checkout_completed för varje order
  • Returer per rad, med frakt återbetald utanför Custas
  • Presentkort utfärdas och mejlas med nycklar härledda från ordern
  • member.merged och member.deleted hanteras
  • Byggt mot en cust_test_-nyckel innan du går live