Payment sessions
A payment session is one checkout for one amount, hosted on checkout.borga.is or embedded on your page.
Creating a session creates a Payment and a checkout to collect it. Hosted sessions return a url to redirect the payer to; embedded sessions return a client_secret for borga.js. Sessions expire after 24 hours.
The payment session object
ps_.null for embedded sessions.pcs_.open, complete or expired.hosted or embedded. This is the checkout mode, not test or live.card, apple_pay, google_pay, bank_invoice.?session=ps_… appended. Empty for embedded sessions and for hosted sessions created without one.is or en.Create a payment session
Either amount or payment is required. Hosted sessions take return_url and cancel_url together or not at all; embedded sessions created with a secret key require origin. Publishable keys may only create embedded sessions, and the browser's Origin header must be on the key's allow-list.
Body
payment or line_items is set.amount. Cannot be combined with payment, which inherits that payment's lines. See line items.amount, in basis points (2400 is 24%), for the payment this session creates: its invoice is one line split at this rate. Defaults to your default VAT rate under Settings; ignored, like every rate, while VAT is off there. Cannot be combined with line_items (each line carries its own) or payment (the rate is already on it).exclusive when amount is the net: the payer is charged amount plus the VAT at the resolved rate, and pays amount as sent when the session is priced for an exempt customer. Each line item takes its own instead; cannot be combined with line_items or payment. See prices without VAT.ISK (no minor unit), EUR, USD, GBP, DKK, NOK, SEK
created instead of creating one.hosted redirects to checkout.borga.is; embedded returns a client_secret for borga.js.http://localhost is allowed in test mode. Give it with cancel_url, or leave both out and the payer stays on the confirmation page.return_url.https://host of the page that opens the modal. Ignored for publishable keys, which use the request's Origin.save_payment_method to attach the card somewhere you can find it.bank_invoice to offer krafa (hosted only, PayDay required).is or en.{ items: [{ price, quantity? }], promotion_code? }. A promotion_code is checked now and redeemed on the subscription when the payment succeeds; quote the discounted first period with POST /v1/subscriptions/quote and send that as amount. Starts a subscription with these recurring prices when the payment succeeds; amount is charged as the first period upfront and should equal one period of the items. Implies save_payment_method.// POST /checkout (Next.js App Router route handler)
export async function POST() {
const session = await borga.paymentSessions.create(
{
amount: 12900,
currency: "ISK",
customer_email: "anna@example.is",
external_reference: "order_5678",
return_url: "https://yoursite.is/order/complete",
cancel_url: "https://yoursite.is/cart",
enabled_methods: ["card", "apple_pay", "google_pay"],
locale: "is",
metadata: { order_id: "5678" },
},
// Your own idempotency key makes retries across processes safe too.
{ idempotencyKey: "order_5678_checkout" },
);
// Send the payer to the hosted page. session.url is absolute.
return Response.redirect(session.url!, 303);
}curl https://api.borga.is/v1/payment_sessions \
-H "Authorization: Bearer sk_test_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order_5678_checkout" \
-d '{
"amount": 12900,
"currency": "ISK",
"customer_email": "anna@example.is",
"external_reference": "order_5678",
"return_url": "https://yoursite.is/order/complete",
"cancel_url": "https://yoursite.is/cart",
"enabled_methods": ["card", "apple_pay", "google_pay"],
"locale": "is",
"metadata": { "order_id": "5678" }
}'{
"id": "ps_3kD9mQ2vXb7LpR4tYw8Nz1Ha",
"payment": "pay_7Hs2Kq9LmW4xZc1Vb8Ny3Rt6",
"url": "https://checkout.borga.is/ps_3kD9mQ2vXb7LpR4tYw8Nz1Ha",
"return_url": "https://yoursite.is/order/complete",
"cancel_url": "https://yoursite.is/cart",
"expires_at": "2026-09-08T12:03:58.201Z",
"status": "open",
"enabled_methods": ["card", "apple_pay", "google_pay"],
"mode": "hosted",
"locale": "is",
"customer_email": "anna@example.is",
"customer_kennitala": null,
"created_at": "2026-09-07T12:03:58.201Z",
"client_secret": null
}Errors: missing_amount, missing_redirect_urls, redirect_url_not_allowed, missing_origin, origin_not_allowed, publishable_key_not_allowed, bank_invoice_not_enabled, invalid_kennitala, resource_not_found.
Retrieve a payment session
Returns the session with payment_status, which saves a second call on your return page. client_secret is never returned here.
curl https://api.borga.is/v1/payment_sessions/ps_3kD9mQ2vXb7LpR4tYw8Nz1Ha \
-H "Authorization: Bearer sk_test_…"There is no list endpoint for sessions and no way to cancel one early; unpaid sessions expire on their own.