# Create Checkout Session - Card, Vipps, Apple & Google Pay

The Create Checkout Session API enables merchants to generate secure, one-time checkout sessions for customers. This ensures a quick and PCI-compliant payment process without requiring the customer to create an account or save a payment method.

### Key use cases
- **E-commerce**: Generate links for one-off product sales.  
- **Services**: Request upfront payments (consulting, events, classes).
  
#### Prerequisites

Before you start the integration, make sure you have:

**1. API Access:**
* A valid API key and Bearer Token from Front Payment
* Access to the demo and production environments

**2. Merchant Setup:**
* Your merchant account configured with Front Payment
* Enabled payment methods (Vipps, Google Pay, Apple Pay, Visa, Mastercard)

**3. Technical Requirements:**
* Ability to make HTTPS API calls
* Secure storage of tokens and keys
* Callback endpoints to handle payment status updates

**4. Test Environment:**
* For testing, contact `nafees.faraz@frontpayment.no` to gain access to the demo environment

### Step 1: Create Payment URL

To initiate a payment, your system will need to call our create endpoint to generate a payment URL. This URL will redirect your users to payment gateway.

#### Endpoint
```
POST https://demo-api.frontpayment.no/api/v1/connect/orders/regular/submit
```

#### Authorization


Include a **Bearer Token** in the `Authorization` header. You can obtain this token from **Front Payment**.

**Example:**  
```
Authorization: Bearer YOUR_FRONTPAYMENT_BEARER_TOKEN
```

-----

#### Request Payload
The request body should be a JSON object containing details about the order, customer, and callback URLs.
```json
{
  "products": [
    {
      "name": "Test Product",
      "productId": "1234",
      "quantity": 1,
      "rate": 4500,
      "discount": 0,
      "tax": 12,
      "amount": 4500
    }
  ],
  "orderSummary": {
    "subTotal": 4017.86,
    "totalTax": 482.14,
    "totalDiscount": 0.00,
    "grandTotal": 4500.00,
    "shippingCost": 0.00
  },
  "referenceNo": "",
  "customerReference": "",
  "orderDate": "1754556624",
  "withCustomer": true,
  "customerDetails": {
    "type": "private",
    "countryCode": "+47",
    "msisdn": "46567468",
    "email": "kari@nordmann.no",
    "name": "Kari Nordmann",
    "preferredLanguage": "en",
    "personalNumber": null,
    "organizationId": null,
    "address": {
      "street": "Luramyrveien 65",
      "zip": "4313",
      "city": "Sandnes",
      "country": "NO"
    }
  },
  "submitPayment": {
    "via": "visa"
  },
  "callback": {
    "callbackUrl": "https://your-callback-url.com/callback",
    "success": "https://your-callback-url.com/success",
    "failure": "https://your-callback-url.com/failure"
  }
}
```

-----
#### Validation Rules
Ensure your payload adheres to the following validation rules:

<table>
  <thead>
    <tr>
      <th style="width: 270px;text-align:left;">Field</th>
      <th style="width: 80px;text-align:left;">Type</th>
      <th style="text-align:left;">Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>products.*.name</code></td>
      <td><code>string</code></td>
      <td><strong>Required</strong>. The name of the product.</td>
    </tr>
    <tr>
      <td><code>products.*.productId</code></td>
      <td><code>string</code></td>
      <td><strong>Optional</strong>. The unique ID of the product.</td>
    </tr>
    <tr>
      <td><code>products.*.quantity</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>.  Quantity of the product.</td>
    </tr>
    <tr>
      <td><code>products.*.rate</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>. Rate per unit of the product.</td>
    </tr>
    <tr>
      <td><code>products.*.discount</code></td>
      <td><code>numeric</code></td>
      <td><strong>Optional</strong>. Discount applied to the product.</td>
    </tr>
    <tr>
      <td><code>products.*.tax</code></td>
      <td><code>numeric</code></td>
      <td> <strong>Required</strong>. Tax rate must be (e.g., 0, 12, 15, 25), Unless you have other configuration unless otherwise configured.</td>
    </tr>
    <tr>
      <td><code>products.*.amount</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>. Total amount for the product line item.</td>
    </tr>
    <tr>
      <td><code>orderSummary.subTotal</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>. Subtotal of all products before tax and discount.</td>
    </tr>
    <tr>
      <td><code>orderSummary.totalTax</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>. The total tax for the order.</td>
    </tr>
    <tr>
      <td><code>orderSummary.totalDiscount</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>. Total discount for the order.</td>
    </tr>
    <tr>
      <td><code>orderSummary.grandTotal</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong>. Grand total of the order.</td>
    </tr>
    <tr>
      <td><code>orderSummary.shippingCost</code></td>
      <td><code>numeric</code></td>
      <td><strong>Optional</strong>. Shipping cost of order.</td>
    </tr>
    <tr>
      <td><code>orderDate</code></td>
      <td><code>string</code></td>
      <td><strong>Required</strong>. Unix timestamp for the Date of the order, which must be current or future date. </td>
    </tr>
    <tr>
      <td><code>referenceNo</code></td>
      <td><code>string</code></td>
      <td><strong>Optional</strong>. Any reference information from your side. example: Order Uuid generated from your application.</td>
    </tr>
    <tr>
      <td><code>customerReference</code></td>
      <td><code>string</code></td>
      <td><strong>Optional</strong>. Customer reference </td>
    </tr>
    <tr>
      <td><code>orderFrom</code></td>
      <td><code>string</code></td>
      <td><strong>Conditionally Required</strong> if <code>fpgoUuid</code> is present. If provided, the value must be <code>PARTNER</code>. This indicates that the request originates from a registered partner and is intended to update an existing record.</td>
    </tr>
    <tr>
      <td><code>fpgoUuid</code></td>
      <td><code>string</code></td>
      <td><strong>Optional</strong> Use this to <strong>prevent duplicates</strong>. Pass the <code>orderUuid</code> from a previous response to update that specific order. If omitted, a new order is created. </td>
    </tr>
    <tr>
      <td><code>withCustomer</code></td>
      <td><code>boolean</code></td>
      <td><strong>Required</strong>. If <strong>withCustomer</strong> is true then you must provide customer details </td>
    </tr>
    <tr>
      <td><code>customerDetails.type</code></td>
      <td><code>string</code></td>
      <td>The customer type. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>. Must be either `private` or `corporate`.</td>
    </tr>
    <tr>
      <td><code>customerDetails.countryCode</code></td>
      <td><code>string</code></td>
      <td> Country code for the customer's phone number (e.g., "+47"). <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.msisdn</code></td>
      <td><code>string</code></td>
      <td>Mobile Subscriber MSISDN Number (phone number). <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.email</code></td>
      <td><code>string</code></td>
      <td>Customer's email address. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.name</code></td>
      <td><code>string</code></td>
      <td>Customer's full name. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.preferredLanguage</code></td>
      <td><code>string</code></td>
      <td><strong>Optional</strong>. Customer preferred language. Available languages are <code>en</code>,<code>no</code>,<code>sv</code>,<code>da</code>,<code>de</code>. If nothing is given it will set default to <code>no</code>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.personalNumber</code></td>
      <td><code>string</code></td>
      <td><strong>Optional</strong>. Customer's personal identification number, must be 11 characters.</td>
    </tr>
    <tr>
      <td><code>customerDetails.organizationId</code></td>
      <td><code>numeric</code></td>
      <td><strong>Required</strong> if customer type is <em>corporate</em>. Must be alphanumeric.</td>
      </tr>
    <tr>
      <td><code>customerDetails.address.street</code></td>
      <td><code>string</code></td>
      <td>Street address of the customer. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.address.zip</code></td>
      <td><code>string</code></td>
      <td>Zip code of the customer's address. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.address.city</code></td>
      <td><code>string</code></td>
      <td>City of the customer's address. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>customerDetails.address.country</code></td>
      <td><code>string</code></td>
      <td>ISO Alpha-2 country code (e.g., "NO"). Custom validation IsoAlpha2Country applies. <strong>Required</strong> if <strong>withCustomer</strong> is <em>true</em>.</td>
    </tr>
    <tr>
      <td><code>submitPayment.via</code></td>
      <td><code>string</code></td>
      <td><strong>Required</strong>. The payment method. Available payment methods <code>vipps</code>, <code>visa</code>, <code>mastercard</code>, <code>applepay</code>, or <code>googlepay</code>.</td>
    </tr>
    <tr>
      <td><code>callback.callbackUrl</code></td>
      <td><code>url</code></td>
      <td><strong>Required</strong>. The URL to which Front Payment will send updates. Must be a valid url.</td>
    </tr>
    <tr>
      <td><code>callback.success</code></td>
      <td><code>url</code></td>
      <td><strong>Required</strong>. The URL to redirect to upon successful payment. Must be a valid url.</td>
    </tr>
    <tr>
      <td><code>callback.failure</code></td>
      <td><code>url</code></td>
      <td> <strong>Required</strong>. The URL to redirect to upon failed payment. Must be a valid url.</td>
    </tr>
  </tbody>
</table>

-----



#### Response

##### Success Response (HTTP 201)
A successful request will return a 201 Created status with the following JSON payload:

```json
{
  "status_code": 201,
  "status_message": "OK",
  "message": "Order Submitted Successfully",
  "is_data": true,
  "data": {
    "orderUuid": "ODR123456789",
    "customerUuid": "CSRT40567996",
    "paymentUrl": "https://v1.checkout.bambora.com/a403d3df20af4888bd8f7dd38f3cd7f1"
  }
}
```

##### Error Responses

**HTTP 500: Internal Dependency Error**

```json
{
  "status_code": 500,
  "status_message": "Internal Dependency Error",
  "message": "Internal Error Occurred Please Try Again Later",
  "is_error": true,
  "errors": {
    "happenedAt": "String",
    "internalErrorDetails": "Array"
  }
}
```

**HTTP 510: Execution Exception**

```json
{
  "status_code": 510,
  "status_message": "Execution Exception Occurred",
  "message": "Something Went Wrong",
  "is_error": true,
  "errors": "Array"
}
```

### Step 2: Redirect to the Payment Gateway

After you successfully complete Step 1, you'll receive a **paymentUrl**. Redirect the user to this payment gateway, so they can make payment and complete the transaction.

After the user completes their payment, our system redirects them back to your application:

* If the payment is successful, they are redirected to the **success URL** you provided.
* If the payment fails, they are redirected to the **failure URL** you provided.

Additionally, our system will send a notification to the **callbackUrl** you gave in your initial request payload, updating your system on the payment status.

### Notifications via Callback URL

For `paymentLink` order, after payment completed successfully, we will notify your server via the `callbackUrl` provided by you. Follow the link below to learn how to handle callback data from your side.

[Go To `Notication Via Callback Url` Page](https://docs.frontpayment.no/books/fpgo-connect/page/notifications-via-callback-url)

### Best Practices
- Always validate amounts on your backend before marking payment as successful.  
- Use **webhooks (callbackUrl)** as your source of truth, not just redirects.  
- Ensure `orderDate` is a valid Unix timestamp and not expired.  
- For corporate customers, `organizationId` is mandatory.