Hoppa till innehållet

Presentkort

Åtta slutpunkter täcker hela kortets liv genom API:et: utfärda, lista, slå upp, lös in, ångra, omskicka, annullera och återbetala.

Annullera kan inte ångras. Det finns ingen återaktivering, eftersom ett kort som dödades och sedan tyst väcktes till liv igen är en skuld som ingen har sagt ja till. Återbetala är den enda slutpunkten som flyttar pengar: Stripe skickar tillbaka beloppet till kortet som betalade, och ingen annanstans.

Prova det här på sidan

Konsolen nedan kör samma scheman och samma inlösningsregel som API:t, mot ett kort som bara finns i din browser. Redigera bodyn, och se vilken status ditt eget anrop skulle få.

Konsolen

Kort
KUV-DLT2-9GPW
Saldo
500,00 Dkr
Status
active

Förfrågan

GET /v1/api/giftcards/KUV-DLT2-9GPW

Authorization: Bearer pk_test_…

Ingen kropp. Koden står i sökvägen.

Svar

200 OK

{
  "giftCard": {
    "id": "gc_3n8qk2vh",
    "code": "KUV-DLT2-9GPW",
    "orderId": null,
    "status": "active",
    "initialOre": 50000,
    "balanceOre": 50000,
    "expiresAt": "2029-01-15T12:00:00.000Z",
    "merchantSlug": "cafe-noir",
    "origin": "b2b",
    "reference": "Faktura 2026-114",
    "punchValueOre": null,
    "noCashClaim": false,
    "productName": null
  }
}

Saldot räknas ut från posteringarna i stället för att läsas från ett fält. Därför stämmer det alltid med inlösningarna.

Svar 200 OK. Saldot räknas ut från posteringarna i stället för att läsas från ett fält. Därför stämmer det alltid med inlösningarna.

Konsolen gör inga anrop ut på nätet. Den kör samma scheman och samma inlösenregel som API:et, mot ett kort som bara finns i din webbläsare. Statuskoder och feltexter är därför de som din egen integration får.

Idempotens

Utfärda och lösa in kan båda ha en nyckel som gör anropet säkert att upprepa. Samma nyckel två gånger svarar med resultatet från den FÖRSTA gången (samma kort, samma post) i stället för att utfärda eller dra två gånger. De två verben upptäcker dock inte samma sak: vid LÖSA IN svarar vi 409 idempotency_key_conflict om nyckeln redan har använts på ett annat kort eller på en utbetalning, i stället för att träffa fel. Vid UTFÄRDA jämför vi inte anropet. Återanvänder du en nyckel med ett annat belopp får du 201 och det FÖRSTA kortets data tillbaka, utan fel. Använd en nyckel per kort.

Nyckeln kan stå på tre platser. Vi läser idempotencyKey i bodyn först, och annars headern Idempotency-Key och sedan X-Request-Guid. Bodyn vinner, när det finns både och.

VarNamn
BodynidempotencyKey: det uttryckliga valet, och det som vinner.
HeaderIdempotency-Key: namnet som Stripe har gjort till standard.
HeaderX-Request-Guid, så att en integration som flyttar från Lifepeaks fungerar utan att skrivas om.

Utfärda ett kort

POST/v1/api/giftcards

Utfärdar ett kort utanför betalningsflödet, t.ex. sålt från ditt eget system, fakturerat till ett företag eller bjudet på av huset.

origin är obligatorisk här, där det är valfritt i kontrollpanelen. Ett system utfärdar utan att någon tittar, och valet följer kortet resten av dess livslängd: sold betyder att en kund har betalat för det, och då bär kortet kundens rätt att få restbeloppet utbetalt kontant. b2b och comp gör inte.

curl -X POST https://api.kuvert.dk/v1/api/giftcards \
  -H "Authorization: Bearer $KUVERT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amountOre": 50000,
    "origin": "b2b",
    "reference": "Faktura 2026-114",
    "idempotencyKey": "faktura-2026-114"
  }'
201 CreatedJSON
{
  "giftCard": {
    "id": "gc_4f1c9a2e7b3d48e6a0c5d9f2b8e1a7c3",
    "code": "KUV-7K9F-2XQD",
    "orderId": null,
    "status": "active",
    "initialOre": 50000,
    "balanceOre": 50000,
    "expiresAt": "2029-09-29T08:00:00.000Z",
    "merchantSlug": "cafe-noir",
    "origin": "b2b",
    "reference": "Faktura 2026-114",
    "punchValueOre": null,
    "noCashClaim": false,
    "productName": null
  }
}
Prova i konsolen

Body

amountOreintegerObligatorisk
Kortets värde i öre, minst 1 öre och högst 100 000,00 Dkr.
origin"sold" | "b2b" | "comp"Obligatorisk
sold: en kund har betalat. b2b: fakturerat till ett företag. comp: bjudet på av huset.
validityMonthsintegerValfri
Giltighet i månader, minst 36 och högst 600. Utelämnas den gäller kortet i 36.
referencestring | nullValfri
Din egen anteckning, t.ex. ett fakturanummer. Högst 200 tecken.
noCashClaimbooleanValfri
Markera kortet «kan inte växlas in mot kontanter», till exempel när det gäller en bestämd sak. Det gör inte i sig en personalgåva skattefri: den danska skattemyndigheten SKAT räknar digitala presentkort som skattepliktiga. Bara på b2b och comp.
idempotencyKeystringValfri
Samma nyckel två gånger utfärdar bara ett kort. Högst 120 tecken. Kan också skickas som header (se Idempotens).

Svarsfält

Kortet ligger under giftCard, i samma form som vid Slå upp ett kort, där fälten beskrivs.

Statuskoder

  • 201

    Kortet är utfärdat. Med en idempotencyKey som har använts tidigare är svaret det kort som nyckeln utfärdade första gången.

  • 400invalid_issue_request

    Kroppen matchar inte det som utfärdning kräver.

  • 404merchant_not_found

    Nyckeln är giltig, men företaget bakom den finns inte längre. Det händer sällan och kan inte rättas av en klient. Kontakta oss.

  • 409cash_claim_cannot_be_denied

    noCashClaim på ett sold-kort. Kunden har betalat, och rätten att få restbeloppet utbetalt kan en flagga inte ta bort.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Lista kort

GET/v1/api/giftcards

Alla företagets kort, nyaste först, med saldot uträknat ur transaktionerna i samma ögonblick. Listan är inte sidindelad.

curl https://api.kuvert.dk/v1/api/giftcards \
  -H "Authorization: Bearer $KUVERT_API_KEY"
200 OKJSON
{
  "giftCards": [
    {
      "id": "gc_4f1c9a2e7b3d48e6a0c5d9f2b8e1a7c3",
      "code": "KUV-7K9F-2XQD",
      "orderId": null,
      "status": "active",
      "initialOre": 50000,
      "balanceOre": 50000,
      "expiresAt": "2029-09-29T08:00:00.000Z",
      "merchantSlug": "cafe-noir",
      "origin": "b2b",
      "reference": "Faktura 2026-114",
      "punchValueOre": null,
      "noCashClaim": false,
      "productName": null
    },
    {
      "id": "gc_9b2e61d04c7f4a3e8d5b1c6a0f2e9d47",
      "code": "KUV-M4TQ-8WZR",
      "orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
      "status": "active",
      "initialOre": 50000,
      "balanceOre": 43600,
      "expiresAt": "2029-06-12T14:31:07.000Z",
      "merchantSlug": "cafe-noir",
      "origin": "paid",
      "reference": null,
      "punchValueOre": null,
      "noCashClaim": false,
      "productName": "Gavekort"
    }
  ]
}

Svarsfält

Korten ligger under giftCards, vart och ett i samma form som vid Slå upp ett kort.

Statuskoder

  • 200

    Listan, eventuellt tom.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Används ofta tillsammans med

Slå upp ett kort

GET/v1/api/giftcards/{code}

Ett kort utifrån dess kod, med saldot som det står just nu.

curl https://api.kuvert.dk/v1/api/giftcards/KUV-7K9F-2XQD \
  -H "Authorization: Bearer $KUVERT_API_KEY"
200 OKJSON
{
  "giftCard": {
    "id": "gc_4f1c9a2e7b3d48e6a0c5d9f2b8e1a7c3",
    "code": "KUV-7K9F-2XQD",
    "orderId": null,
    "status": "active",
    "initialOre": 50000,
    "balanceOre": 50000,
    "expiresAt": "2029-09-29T08:00:00.000Z",
    "merchantSlug": "cafe-noir",
    "origin": "b2b",
    "reference": "Faktura 2026-114",
    "punchValueOre": null,
    "noCashClaim": false,
    "productName": null
  }
}
Prova i konsolen

Sökvägsparametrar

codestringObligatorisk
Kortets kod, t.ex. KUV-7K9F-2XQD.

Svarsfält

Kortet ligger under giftCard:

idstring
Kortets id (gc_…). Koden är det du slår upp med.
codestring
Koden som står på kortet.
orderIdstring | null
Ordern som kortet kom från. null för ett kort som utfärdats för hand eller via API:t.
status"active" | "redeemed" | "expired" | "void" | "disputed"
Kortets tillstånd. Bara active kan lösas in.
initialOreinteger
Kortets värde i öre, innan något lösts in.
balanceOreinteger
Saldot i öre, uträknat ur posterna och inte läst från ett fält.
expiresAtstring
När kortet löper ut, ISO 8601 i UTC.
merchantSlugstring
Butikens adress på shop.kuvert.dk.
origin"paid" | "sold" | "b2b" | "corporate" | "comp"
Var värdet kom ifrån. paid är köpt i butiken och corporate köpt som företagsgåva; sold, b2b och comp är utfärdade för hand eller via API:t.
referencestring | null
Din egen anteckning från utfärdandet. null på ett köpt kort.
punchValueOreinteger | null
Värdet av ett klipp om kortet är ett klippkort, annars null. Ett klippkort löses in i hela klipp.
noCashClaimboolean
Kortet kan inte växlas in mot kontanter.
productNamestring | null
Produktens namn som det löd när kortet utfärdades. null på ett kort som utfärdats för hand.

Statuskoder

  • 200

    Kortet.

  • 400not_a_gift_card

    Koden i sökvägen är en biljettskod (TKT-…), inte ett presentkort.

  • 404gift_card_not_found

    Koden finns inte på ditt företag.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Lösa in

POST/v1/api/giftcards/{code}/redeem

Drar ett belopp från kortets saldo. Koden står i sökvägen, beloppet i bodyn.

Spara id. Det är posteringen, och det är det enda som kan ångra just denna inlösning.

Om det inte går igenom, är svaret en av dessa. De är inte samma för kassan: några är något gästen bör veta, och några är något företaget bör ringas om.

curl -X POST https://api.kuvert.dk/v1/api/giftcards/KUV-7K9F-2XQD/redeem \
  -H "Authorization: Bearer $KUVERT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amountOre": 6400,
    "location": "Vesterbro",
    "idempotencyKey": "pos-3-20260929-0142"
  }'
200 OKJSON
{
  "id": "red_8f21c0b45d3e4a9b8c7d6e5f4a3b2c1d",
  "code": "KUV-7K9F-2XQD",
  "amountOre": 6400,
  "remainingBalanceOre": 43600,
  "status": "active"
}
Prova i konsolen

Sökvägsparametrar

codestringObligatorisk
Kortets kod, t.ex. KUV-7K9F-2XQD.

Body

amountOreintegerObligatorisk
Beloppet i öre, minst 1. Ett klippkort tar bara ett helt antal klipp.
locationstring | nullValfri
Var det skedde, t.ex. «Vesterbro». Högst 120 tecken.
idempotencyKeystringValfri
Samma nyckel två gånger drar bara en gång. Högst 120 tecken. Kan också skickas som header (se Idempotens).

Svarsfält

Svaret är transaktionen:

idstring
Postens id (red_…), som du ångrar den med.
codestring
Kortets kod.
amountOreinteger
Det dragna beloppet i öre.
remainingBalanceOreinteger
Saldot efter inlösningen.
status"active" | "redeemed" | "expired" | "void" | "disputed"
status är kortets status efter inlösen, en av active, redeemed, expired, void, disputed. Är saldot förbrukat ändras den till redeemed.

Statuskoder

  • 200

    Beloppet är draget. Med en idempotencyKey som har använts tidigare på samma kort är svaret det från första gången, utan att något dras igen.

  • 400invalid_redeem_request

    Bodyn matchar inte det som inlösen kräver, vanligtvis ett belopp som inte är ett helt antal öre eller som är noll.

  • 400not_a_gift_card

    Koden i sökvägen är en biljettskod (TKT-…), inte ett presentkort.

  • 404gift_card_not_found

    Koden finns inte på ditt företag.

  • 409card_inactive

    Kortet är inte aktivt: förbrukat, annullerat, satt till utgånget eller fryst under en tvist. Det går inte över av sig självt, så företaget behöver kontaktas.

  • 409redeem_too_soon

    Företaget har satt en inlösningsfördröjning, och den är inte utgångsen än. Kortet har inget fel; det kan bara inte användas än. Försök igen senare.

  • 409idempotency_key_conflict

    Nyckeln har redan använts på ett annat kort eller på en utbetalning från samma kort. Se Idempotens.

  • 410gift_card_expired

    Kortet står fortfarande som aktivt, men utgångsdatumet har passerat. Till skillnad från card_inactive är det tiden och inte ett beslut som har stängt kortet.

  • 422insufficient_balance

    Beloppet är större än saldot. Vi drar aldrig ett delbelopp på eget initiativ. Slå upp kortet, dra saldot och ta resten på annat sätt.

  • 422invalid_amount

    Inlösningsregelns eget svar på ett olagligt belopp. Schemat fångar det normalt redan som 400 invalid_redeem_request, så en klient bör kunna läsa båda.

  • 422punch_amount_not_whole

    Kortet är ett klippkort, och beloppet är inte ett helt antal klipp. Det är inget fel på talet, men det är fel sorts kort för det. Slå upp kortet, läs punchValueOre och skicka det värdet eller en multipel av det. Ett klippkort som blir kvar med en rest under ett klipp är pengar som varken kassan eller kunden kan komma åt.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Ångra en inlösning

POST/v1/api/redemptions/{id}/reverse

Lägger tillbaka beloppet på kortet. Det sker som en ny post med negativt belopp som pekar på den post den ångrar. Ingenting raderas, och båda raderna står kvar i kortets historik. Var kortet helt förbrukat blir det aktivt igen.

curl -X POST https://api.kuvert.dk/v1/api/redemptions/red_8f21c0b45d3e4a9b8c7d6e5f4a3b2c1d/reverse \
  -H "Authorization: Bearer $KUVERT_API_KEY"
200 OKJSON
{
  "id": "red_2c77af90e1d24b3c9a8f7e6d5c4b3a21",
  "code": "KUV-7K9F-2XQD",
  "amountOre": -6400,
  "remainingBalanceOre": 50000,
  "status": "active"
}

Sökvägsparametrar

idstringObligatorisk
Inlösningens id (red_…), som du fick tillbaka från Lösa in.

Svarsfält

Svaret är posten som lade tillbaka beloppet, i samma form som vid Lös in, med negativt amountOre.

Statuskoder

  • 200

    Beloppet är tillbakalagt.

  • 404redemption_not_found

    Posteringen finns inte på ditt företag.

  • 409already_reversed

    Den är ångråd tidigare. En gång, aldrig två.

  • 409not_reversible

    Posteringen är själv en ångran eller en kontant utbetalning.

  • 409card_inactive

    Kortet är annullerat eller fryst under en invänd.

  • 409order_refunded

    Beställningen bakom kortet är återbetald. Köparen har redan fått pengarna tillbaka, så en ångran skulle ge dem värdet två gånger.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Används ofta tillsammans med

Skicka kortet igen

POST/v1/api/giftcards/{code}/resend

Skickar kortet till mottagaren igen. Det är vad en kassa gör när en kund säger att mejlet aldrig kom.

Utan recipient skickar vi det som kortets order ännu inte har fått levererat, till den adress som står angiven. Ett kort som redan har levererats skickas inte igen. Med recipient rättar du adressen på just det här kortet och skickar det dit, även om det har levererats tidigare. Bara aktiva kort skickas.

curl -X POST https://api.kuvert.dk/v1/api/giftcards/KUV-M4TQ-8WZR/resend \
  -H "Authorization: Bearer $KUVERT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "recipient": "ny-adresse@dit-domaene.dk"
  }'
200 OKJSON
{
  "delivered": 1
}

Sökvägsparametrar

codestringObligatorisk
Kortets kod, t.ex. KUV-7K9F-2XQD.

Body

recipientstringValfri
En ny e-postadress för kortet. Bodyn kan utelämnas helt.

Svarsfält

Svaret anger hur mycket som skickades:

deliveredinteger
Antal kort som skickades. 0 betyder att det inte fanns något att skicka.

Statuskoder

  • 200

    Skickat, eller inget att skicka.

  • 400not_a_gift_card

    Koden i sökvägen är en biljettskod (TKT-…), inte ett presentkort.

  • 404gift_card_not_found

    Koden finns inte på ditt företag.

  • 404order_not_found

    Omskicka hittade kortet, men inte den order det kom från. Ett kort utfärdat för hand har ingen order och kan därför inte omskickas på det sättet.

  • 409card_has_no_delivery

    Kortet har aldrig skickats av oss, eftersom det lämnades ut över disken. Det finns ingen leverans att upprepa.

  • 422invalid_recipient

    recipient i body för omskicka är inte en e-postadress vi kan skicka till. Utelämna fältet för att skicka till den adress kortet redan har.

  • 502delivery_failed

    Vi nådde vår leverantör, och den avvisade försändelsen. Det är inget fel på kortet, och ingenting har dragits. Försök igen eller kontrollera adressen.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Används ofta tillsammans med

Annullera ett kort

POST/v1/api/giftcards/{code}/cancel

Annullerar kortet omedelbart. Saldot står kvar på kortet men kan inte längre användas, och det går inte att ångra. Är kortet redan annullerat får du tillbaka det som det är, utan fel.

curl -X POST https://api.kuvert.dk/v1/api/giftcards/KUV-7K9F-2XQD/cancel \
  -H "Authorization: Bearer $KUVERT_API_KEY"
200 OKJSON
{
  "giftCard": {
    "id": "gc_4f1c9a2e7b3d48e6a0c5d9f2b8e1a7c3",
    "code": "KUV-7K9F-2XQD",
    "orderId": null,
    "status": "void",
    "initialOre": 50000,
    "balanceOre": 50000,
    "expiresAt": "2029-09-29T08:00:00.000Z",
    "merchantSlug": "cafe-noir",
    "origin": "b2b",
    "reference": "Faktura 2026-114",
    "punchValueOre": null,
    "noCashClaim": false,
    "productName": null
  }
}

Sökvägsparametrar

codestringObligatorisk
Kortets kod, t.ex. KUV-7K9F-2XQD.

Svarsfält

Kortet ligger under giftCard, nu med status void.

Statuskoder

  • 200

    Kortet är annullerat, eller var det redan.

  • 400not_a_gift_card

    Koden i sökvägen är en biljettskod (TKT-…), inte ett presentkort.

  • 404gift_card_not_found

    Koden finns inte på ditt företag.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Återbetala en order

POST/v1/api/orders/{id}/refund

Skickar tillbaka hela betalningen för ordern till kortet som betalade, inklusive köparens expeditionsavgift, och Kuverts avgift på försäljningen går tillbaka till dig. Det är den enda slutpunkten som flyttar pengar.

När Stripe har bekräftat återbetalningen tas värdet av orderns kort, dess biljetter annulleras och order.refunded skickas. Det sker oftast några sekunder efter svaret.

Anropet tar ingen idempotensnyckel, eftersom orderns egen status är spärren. En order som redan har återbetalats svarar 409 order_not_refundable.

curl -X POST https://api.kuvert.dk/v1/api/orders/ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c/refund \
  -H "Authorization: Bearer $KUVERT_API_KEY"
200 OKJSON
{
  "orderId": "ord_7d3f0b9c1e2a45f68b4c9d0e1f2a3b5c",
  "refundId": "re_3PqX9aLkT2mN8vRb1c4D7eFg",
  "amountOre": 50500
}

Sökvägsparametrar

idstringObligatorisk
Orderns id (ord_…): orderId på kortet eller i order.paid.

Svarsfält

Svaret är återbetalningen så som Stripe tog emot den:

orderIdstring
Ordern.
refundIdstring
Stripes id för återbetalningen (re_…), som du hittar den under i Stripe.
amountOreinteger
Beloppet som skickas tillbaka, i öre.

Statuskoder

  • 200

    Stripe har tagit emot återbetalningen.

  • 404order_not_found

    Ordern finns inte hos ditt företag.

  • 409order_not_refundable

    Ordern kan inte återbetalas: den är inte betald, redan återbetald eller fryst under en tvist.

  • 409merchant_not_payment_ready

    Ditt Stripe-konto är inte anslutet.

  • 503stripe_not_configured

    Betalningar är tillfälligt otillgängliga hos oss. Försök igen senare.

Ett fel har alltid formen { "error": "…" }. Varje anrop kan dessutom svara 401, 403, 429 och 500. Se Fel.

Används ofta tillsammans med

Var sidan till hjälp?