> ## Documentation Index
> Fetch the complete documentation index at: https://docs.borga.is/llms.txt
> Use this file to discover all available pages before exploring further.

# How payments work in Borga

> Learn about the payment object, lifecycle, supported payment methods, hosted and embedded checkout sessions, refunds, and saved payment methods.

A payment in Borga represents a single charge attempt against a customer. You create a payment by providing an amount and currency — Borga handles the rest, moving the charge through a predictable lifecycle and producing a legally compliant invoice automatically. Whether you accept cards, Apple Pay, Google Pay, or bank invoices (krafa), all payment types flow through the same object model.

## The payment object

When you create or retrieve a payment, the response includes the following key fields:

| Field                | Type   | Description                                                |
| -------------------- | ------ | ---------------------------------------------------------- |
| `id`                 | string | Unique identifier for the payment, e.g. `pay_01HXYZ…`      |
| `amount`             | number | Charge amount in the smallest currency unit (ISK, integer) |
| `currency`           | string | ISO 4217 currency code, e.g. `ISK`                         |
| `status`             | string | Current lifecycle status (see below)                       |
| `customer`           | string | ID of the customer being charged, if provided              |
| `description`        | string | Human-readable description shown on the invoice            |
| `external_reference` | string | Your own order or reference ID for reconciliation          |
| `metadata`           | object | Up to 50 key-value pairs for your own structured data      |

<Tip>
  Use `external_reference` to store your internal order ID. It is indexed, making it easy to look up a Borga payment from your own system.
</Tip>

## Payment lifecycle

Every payment moves through a fixed sequence of statuses. Understand which status you are in before taking further action.

```mermaid theme={null}
flowchart LR
    A[created] --> B[processing]
    B --> C[succeeded]
    B --> D[failed]
    C --> E[refunded]
    C --> F[partially_refunded]
```

| Status               | Meaning                                                            |
| -------------------- | ------------------------------------------------------------------ |
| `created`            | The payment record exists but no charge attempt has started.       |
| `processing`         | The charge is in flight — do not retry or cancel at this point.    |
| `succeeded`          | The charge completed. An invoice has been issued.                  |
| `failed`             | The charge was declined or encountered an error. Safe to retry.    |
| `refunded`           | The full amount was refunded.                                      |
| `partially_refunded` | One or more partial refunds have been issued against this payment. |

<Warning>
  Never update your order status based solely on a `succeeded` response from a direct API call. Use webhooks to receive status updates asynchronously and avoid race conditions.
</Warning>

## Payment methods supported

Borga supports the following payment methods. All methods settle in ISK.

<CardGroup cols={2}>
  <Card title="Cards" icon="credit-card">
    Visa and Mastercard. Supports 3D Secure where the card issuer requires it.
  </Card>

  <Card title="Apple Pay" icon="apple">
    Available in Safari on Apple devices. Enabled automatically in payment sessions.
  </Card>

  <Card title="Google Pay" icon="google">
    Available in Chrome and on Android devices. Enabled automatically in payment sessions.
  </Card>

  <Card title="Bank invoice (krafa)" icon="building-columns">
    ISK-only. Borga sends a krafa directly to the customer's netbanki. The customer approves payment from their online bank.
  </Card>
</CardGroup>

<Note>
  Bank invoice (krafa) is only available for ISK payments. It cannot be used for foreign-currency transactions.
</Note>

## Payment sessions

For most checkout flows you should create a payment session rather than a raw payment. A session hosts the payment form, handles 3D Secure redirects, and manages the checkout UI for you. You create a session with `POST /v1/payment_sessions`.

The two session modes are:

<Tabs>
  <Tab title="Hosted">
    Borga renders the full checkout page at a Borga-hosted URL. Redirect your customer to that URL, and Borga redirects them back to your `return_url` or `cancel_url` when the session ends.

    **Best for:** teams that want a complete checkout UI with minimal integration effort.

    ```json theme={null}
    {
      "mode": "hosted",
      "amount": 12900,
      "currency": "ISK",
      "return_url": "https://yoursite.is/order/complete",
      "cancel_url": "https://yoursite.is/cart"
    }
    ```
  </Tab>

  <Tab title="Embedded">
    Borga provides a JavaScript component you embed directly in your own page. The customer never leaves your site.

    **Best for:** teams that want a seamless on-site experience and full control over the surrounding page layout.

    ```json theme={null}
    {
      "mode": "embedded",
      "amount": 12900,
      "currency": "ISK",
      "origin": "https://yoursite.is",
      "return_url": "https://yoursite.is/order/complete"
    }
    ```
  </Tab>
</Tabs>

### Session fields reference

<AccordionGroup>
  <Accordion title="Core fields">
    | Field                | Required | Description                                                     |
    | -------------------- | -------- | --------------------------------------------------------------- |
    | `payment`            | No       | Attach to an existing payment ID instead of creating a new one. |
    | `amount`             | No       | Override amount when not using an existing payment.             |
    | `currency`           | No       | Defaults to `ISK`.                                              |
    | `customer_email`     | No       | Pre-fill the email field in the checkout form.                  |
    | `external_reference` | No       | Your own reference ID, carried through to the payment.          |
    | `metadata`           | No       | Key-value pairs passed to the resulting payment.                |
    | `locale`             | No       | Locale for the checkout UI, e.g. `is` or `en`.                  |
  </Accordion>

  <Accordion title="Flow fields">
    | Field                 | Required | Description                                                            |
    | --------------------- | -------- | ---------------------------------------------------------------------- |
    | `return_url`          | Yes      | URL Borga redirects to after a successful or completed session.        |
    | `cancel_url`          | No       | URL Borga redirects to if the customer cancels.                        |
    | `mode`                | No       | `"hosted"` (default) or `"embedded"`.                                  |
    | `origin`              | No       | Required for `embedded` mode — your site's origin for iframe security. |
    | `enabled_methods`     | No       | Restrict which payment methods appear, e.g. `["card", "krafa"]`.       |
    | `save_payment_method` | No       | If `true`, the card used is saved to the customer for future charges.  |
    | `customer`            | No       | Customer ID to associate the session and any saved method with.        |
  </Accordion>
</AccordionGroup>

## Refunds

Issue a full or partial refund against a succeeded payment with `POST /v1/refunds`.

<CodeGroup>
  ```bash Full refund theme={null}
  curl --request POST \
    --url https://api.borga.is/v1/refunds \
    --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
    --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
    --header "Content-Type: application/json" \
    --data '{
      "payment": "pay_01HXYZ",
      "reason": "customer_request"
    }'
  ```

  ```bash Partial refund theme={null}
  curl --request POST \
    --url https://api.borga.is/v1/refunds \
    --header "Authorization: Bearer sk_test_YOUR_SECRET_KEY" \
    --header "X-Merchant-Id: mer_YOUR_MERCHANT_ID" \
    --header "Content-Type: application/json" \
    --data '{
      "payment": "pay_01HXYZ",
      "amount": 2500,
      "reason": "partial_return"
    }'
  ```
</CodeGroup>

The `amount` field is optional. Omit it to refund the full remaining amount. The `reason` field is a free-form string — use it for internal notes or to pass a reason code to your accounting integration.

When a refund is issued, Borga automatically generates a credit note linked to the original invoice. See [Invoicing](/concepts/invoicing) for details.

## Saved payment methods

When you set `save_payment_method: true` on a payment session and provide a `customer` ID, Borga saves the card used to that customer record for future charges. You can then:

* List saved methods with `GET /v1/payment_methods?customer=cus_…`
* Retrieve a specific method with `GET /v1/payment_methods/{id}`
* Set a method as the customer's default with `POST /v1/payment_methods/{id}/set_default`
* Remove a method with `DELETE /v1/payment_methods/{id}`

The default payment method is used automatically when charging the customer via a subscription with `collection_method: charge_automatically`.
