Create a checkout order
Creating an order in checkout is very simple. After you have your checkout merchantId and checkout merchant secret setup, all you need to do is make a request for order creation.
Make sure your request contains correct authentication headers and that you're using Checkout API URI.
Use this request to create a Checkout order. The response contains the necessary data to embed the Checkout widget on your site.
Quantity, UnitPrice, DiscountPercent, DiscountAmount and VatPercent for each order row expected to be given in minor units.
HTTP status code 201 indicates that a new Checkout order was created.
HTTP status code 200 indicates that an existing Checkout order was found with the provided clientOrderNumber.
To be able to create an order with zero value amount, merchants have to have this feature enabled. Please contact your sales contact for more information.
Endpoint
/api/orders
Request
Body Parameters
- Request Model
- Request Samples
- Code Snippets
Name | Description | Type | Additional Information |
---|---|---|---|
countryCode | String | ||
currency | String | ||
locale | Locale for the order | String | Supported: sv-se, da-dk, de-de, en-us, fi-fi, nn-no. |
clientOrderNumber | A string that identifies the order in the merchant’s systems. The ClientOrderNumber is unique per order. Attempting to create a new order with a previously used ClientOrderNumber will result in the create method returning the already existing order instead. If using Vipps payment method, allowed values are any combination of: A-Z , a-z , 0-9 , - and _ (underscore). Example for Vipps: abc-12d-efg-123 | String | Max length: 32 |
merchantSettings | MerchantSettings | ||
cart | The total cost of the order rows in the cart needs to be equal or higher than 0 but the cart must not be empty. | Cart | Free order items/rows, like gift cards, can have a value of 0, denoting no cost |
presetValues | Collection of PresetValue | ||
identityFlags | IdentityFlags | ||
requireElectronicIdAuthentication | Boolean | ||
partnerKey | Provided by Svea to select partners. | Guid | |
merchantData | Metadata visible to the store | String | Max length: 6000 Cleaned up from Checkout database after 45 days. |
shippingInformation | Shipping information needed for the shipping checkout. Only applicable if merchant has shipping enabled. | ShippingInformation (order) | In order to have the shipping checkout 'enableShipping' should be set to true |
validation | Order validations such as minimum age requirement should be fulfilled here. (It's nullable it means you do not need to provide anything in case the age limit is not required) | OrderValidation | Apply it in order to have order validation such as minimum age / Nullable |
recurring new | Indicates if the order is recurring order and will create a recurring token when order is finalized. Only applicable if merchant has recurring orders enabled. Please check Recurring Order for more details | Boolean / Null | In order to create recurring order this field should be set to true |
- JSON
- CreateOrderRequestModel.cs
{
"countryCode": "SE",
"currency": "SEK",
"locale": "sv-SE",
"clientOrderNumber": "1234ABCD",
"merchantSettings": {
"CheckoutValidationCallBackUri": "https://your.domain/validation-callback/{checkout.order.uri}",
"PushUri": "https://your.domain/push-callback/{checkout.order.uri}",
"TermsUri": "https://your.domain/terms/",
"CheckoutUri": "https://your.domain/checkout-callback/",
"ConfirmationUri": "https://your.domain/confirmation-callback/",
"ActivePartPaymentCampaigns": null,
"PromotedPartPaymentCampaign": 0
},
"cart": {
"Items": [
{
"ArticleNumber": "ABC80",
"Name": "Computer",
"Quantity": 300, // 3.00 units
"UnitPrice": 500000, // 5000.00 SEK
"DiscountPercent": 1000, // 10.00% discount
"VatPercent": 2500, // 25.00% VAT
"Unit": null, // e.g. pcs, kg...
"TemporaryReference": null,
"RowNumber": 1,
"MerchantData": null,
"RowType": "Row" | "ShippingFee",
},
{
"ArticleNumber": "ABC81",
"Name": "Another Computer",
"Quantity": 200, // 2.00 units
"UnitPrice": 400000, // 4000.00 SEK
"DiscountAmount": 10000, // 100.00 SEK discount
"VatPercent": 2500, // 25.00% VAT
"Unit": null, // e.g. pcs, kg...
"TemporaryReference": null,
"RowNumber": 2,
"MerchantData": null,
"RowType": "Row" | "ShippingFee",
}
]
},
"ShippingInformation": {
"EnableShipping": true,
"EnforceFallback": false,
"Weight": 1000.0, // grams
"Tags": {
"bulky": "true",
"key": "value"
//etc
},
"FallbackOptions": [
{
"Id": "145af7a2-e432-48b8-a6ce-2acf0519882a",
"Carrier": "Bring",
"Name": "Home Delivery",
"Price": 29, // 29.00 SEK
"ShippingFee": 2900, // 29.00 SEK
"addons": [{...}],
"fields": [{...}]
}
]
},
"presetValues": [
{
"TypeName": "EmailAddress",
"Value": "test.person@svea.com",
"IsReadonly": true
}
],
"validation": {
"minAge": 18
},
"identityFlags": null,
"requireElectronicIdAuthentication": false,
"partnerKey": null,
"merchantData": null,
"recurring": true //Finalized order will result in a new Recurring Token
}
public class CreateOrderRequestModel
{
public string CountryCode { get; set; } = string.Empty;
public string Currency { get; set; } = string.Empty;
public string Locale { get; set; } = string.Empty;
public string ClientOrderNumber { get; set; } = string.Empty;
public MerchantSettings MerchantSettings { get; set; } = new MerchantSettings()
{
CheckoutUri = "https://loalhost:3000/checkoutPage",
ConfirmationUri = "https://localhost:3000/confirmationPage/clientOrderNumber",
TermsUri = "https://localhost:3000/legalterms",
PushUri = "https://localhost:3000/pushUri"
};
public Cart Cart { get; set; } = new Cart();
public ShippingInformation? ShippingInformation { get; set; }
public List<PresetValue>? PresetValues { get; set; }
public Validation Validation { get; set; } = new Validation();
public IdentityFlags? IdentityFlags { get; set; }
public bool RequireElectronicIdAuthentication { get; set; }
public string? PartnerKey { get; set; }
public string? MerchantData { get; set; }
public bool Recurring { get; set; }
}
public class MerchantSettings
{
public string? CheckoutValidationCallBackUri { get; set; } = string.Empty;
public string PushUri { get; set; } = string.Empty;
public string TermsUri { get; set; } = string.Empty;
public string CheckoutUri { get; set; } = string.Empty;
public string ConfirmationUri { get; set; } = string.Empty;
public List<int>? ActivePartPaymentCampaigns { get; set; }
public int PromotedPartPaymentCampaign { get; set; }
}
public class Cart
{
public List<OrderRow> Items { get; set; } = new List<OrderRow>();
}
public class OrderRow
{
public string? ArticleNumber { get; set; }
public string Name { get; set; } = string.Empty;
public long Quantity { get; set; }
public long UnitPrice { get; set; }
public long DiscountPercent { get; set; }
public long DiscountAmount { get; set; }
public long VatPercent { get; set; }
public string Unit { get; set; } = string.Empty;
public string? TemporaryReference { get; set; }
public int RowNumber { get; set; }
public string? MerchantData { get; set; }
public string? RowType { get; set; }
}
public class ShippingInformation
{
public bool EnableShipping { get; set; }
public bool EnforceFallback { get; set; }
public double Weight { get; set; }
public Dictionary<string, string>? Tags { get; set; }
public List<FallbackOption>? FallbackOptions { get; set; }
public bool ShouldRejectShippingSession { get; set; }
}
public class FallbackOption
{
public string Id { get; set; } = string.Empty;
public string Carrier { get; set; } = string.Empty;
public string Name { get; set; } = string.Empty;
public long ShippingFee { get; set; }
public List<Addon>? Addons { get; set; }
public List<Field>? Fields { get; set; }
}
public class Addon
{
// Properties for Addon
}
public class Field
{
// Properties for Field
}
public class PresetValue
{
public string TypeName { get; set; } = string.Empty;
public string Value { get; set; } = string.Empty;
public bool IsReadonly { get; set; }
}
public class Validation
{
}
public class IdentityFlags
{
public bool HideNotYou { get; set; }
public bool HideChangeAddress { get; set; }
public bool HideAnonymous { get; set; }
}
- CreateOrderSample.cs
- CreateOrderMockRequest.cs
public class CreateOrderSample
{
public static async Task<dynamic> Handle()
{
return await CreateOrder(CreateOrderMockRequest.CreateBaseMockRequestSE());
}
/// <summary>
/// Refer to CreateOrderMockRequest for example of minimal request needed to create a checkout order.
/// </summary>
public static async Task<dynamic> CreateOrder(CreateOrderRequestModel createOrdeRequest)
{
var services = new ServiceCollection();
services.AddHttpClient("MyApiClient", client =>
{
client.BaseAddress = new Uri("https://checkoutapistage.svea.com");
});
var serviceProvider = services.BuildServiceProvider();
var httpClientFactory = serviceProvider.GetRequiredService<IHttpClientFactory>();
var httpClient = httpClientFactory.CreateClient("MyApiClient");
var jsonString = JsonSerializer.Serialize(createOrdeRequest);
var createOrderRequestJson = new StringContent(
jsonString,
Encoding.UTF8,
"application/json");
// Add authorization header
Authentication.CreateAuthenticationToken(out string token, out string timestamp, jsonString);
httpClient.DefaultRequestHeaders.Add("Authorization", token);
httpClient.DefaultRequestHeaders.Add("Timestamp", timestamp);
var apiUrl = "/api/orders";
try
{
HttpResponseMessage response = await httpClient.PostAsync(apiUrl, createOrderRequestJson);
// Check if the request was successful
if (response.IsSuccessStatusCode)
{
var responseData = await response.Content.ReadFromJsonAsync<dynamic>();
Console.WriteLine("Response: " + responseData);
return responseData;
}
else
{
Console.WriteLine("Failed to retrieve data. Status code: " + response.StatusCode);
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("Error: " + ex.Message);
}
return null;
}
}
public class CreateOrderMockRequest
{
public static CreateOrderRequestModel CreateBaseMockRequestSE() => new()
{
CountryCode = "SE",
Currency = "SEK",
Locale = "sv-se",
ClientOrderNumber = Guid.NewGuid().ToString().Replace("-", ""),
MerchantSettings = new MerchantSettings()
{
CheckoutUri = "https://loalhost:3000/checkoutPage",
ConfirmationUri = "https://localhost:3000/confirmationPage/clientOrderNumber",
TermsUri = "https://localhost:3000/legalterms",
PushUri = "https://localhost:3000/pushUri/{checkout.order.uri}"
},
Cart = new Cart()
{
Items = new List<OrderRow>(){
new() {
Name="Article1",
Quantity=500,
UnitPrice=100,
ArticleNumber="123-456-789",
Unit="st"
},
new() {
Name="Article2",
Quantity=500,
UnitPrice=100,
ArticleNumber="123-asd-fgh",
Unit="st"
},
}
}
};
}
Response
- Response Model
- Response Sample
Name | Description | Type | Additional Information |
---|---|---|---|
OrderId | The id of the Order, needed to get and update order in the Checkout API | Int64 | |
ClientOrderNumber | String | ||
Gui | Contains the Snippet that is used to embed the Checkout UI on your site | Gui | |
Status | The current status of the order | CheckoutOrderStatus | |
Cart | Order rows. | Cart | |
Currency | Currency as defined by ISO 4217 | String | |
Locale | The locale of the Checkout, e.g. sv-SE. | String | |
Customer | Customer information | Customer | |
CountryCode | Defined by two-letter ISO 3166-1 alpha-2, e.g. SE, NO, FI, DK | String | |
EmailAddress | Customer's email address | String | |
PhoneNumber | Customer's phone number | String | |
ShippingAddress | Customer's shipping address. | Address | |
BillingAddress | Customer's billing address. | Address | |
PaymentType | The payment method that the customer used to finish the purchase. Only set when order status is Final
| String | |
Payment | The payment method that the customer used to finish the purchase. Only set when order status is Final | PaymentInfo | |
SveaWillBuyOrder | True = Svea will buy this invoice. False = Svea will not buy this invoice. null = Selected payment method is not Invoice. | Boolean | |
MerchantSettings | MerchantSettings | ||
IdentityFlags | IdentityFlags | ||
CustomerReference | B2B Customer reference | String | |
PeppolId | A company’s ID in the PEPPOL network, which allows the company to receive PEPPOL invoices. A PEPPOL ID can be entered when placing a B2B order using the payment method invoice. | String | |
MerchantData | Metadata visible to the store | String | Cleaned up from Checkout database after 45 days. |
ShippingInformation | The returned Shipping information from a previously created/updated order. After the order is finalized and the shipping is created we will include a couple more properties in the ShippingInformation on Order level associated with the Shipping Provider. | GetOrderShippingInformation | |
Recurring new | Indicates if the order is recurring order and will create a recurring token when order is finalized. Only applicable if merchant has recurring orders enabled. | Boolean / Null | |
RecurringToken new | Recurring token to be used for subsequent recurring orders. Only available when order is finalized. Only applicable if merchant has recurring orders enabled. | String / Null | |
BillingReferences | A collection of B2B billing references. | BillingReference | Applicable for B2B orders |
{
"MerchantSettings": {
"CheckoutValidationCallBackUri": "https://your.domain/validation-callback/{checkout.order.uri}",
"PushUri": "https://your.domain/push-callback/{checkout.order.uri}",
"TermsUri": "https://your.domain/terms/",
"CheckoutUri": "https://your.domain/checkout-callback/",
"ConfirmationUri": "https://your.domain/confirmation-callback/",
"ActivePartPaymentCampaigns": [
1111,
2222,
3333,
4444
],
"PromotedPartPaymentCampaign": 1111
},
"Cart": {
"Items": [
{
"ArticleNumber": "ABC80",
"Name": "Computer",
"Quantity": 300, // 3.00 units
"UnitPrice": 500000, // 5000.00 SEK
"DiscountPercent": 1000, // 10.00% discount
"VatPercent": 2500, // 25.00% VAT
"Unit": null, // e.g. pcs, kg...
"TemporaryReference": null,
"RowNumber": 1,
"MerchantData": null,
"RowType": "Row" | "ShippingFee",
},
{
"ArticleNumber": "ABC81",
"Name": "Another Computer",
"Quantity": 200, // 2.00 units
"UnitPrice": 400000, // 4000.00 SEK
"DiscountAmount": 10000, // 100.00 SEK discount
"VatPercent": 2500, // 25.00% VAT
"Unit": null, // e.g. pcs, kg...
"TemporaryReference": null,
"RowNumber": 2,
"MerchantData": null,
"RowType": "Row" | "ShippingFee",
}
]
},
"ShippingInformation": {
"EnableShipping": true,
"EnforceFallback": false,
"Weight": 1000.0, // grams
"Tags": {
"bulky": "true",
"key": "value"
//etc
},
"FallbackOptions": [
{
"Id": "145af7a2-e432-48b8-a6ce-2acf0519882a",
"Carrier": "Bring",
"Name": "Home Delivery",
"Price": 29, // 29.00 SEK
"ShippingFee": 2900, // 29.00 SEK
"addons": [{...}],
"fields": [{...}]
}
],
"ShippingProvider": { //only set when shipping order has been created
"Name": "nShift",
"ShipmentId": "622162",
"ShippingOption": {
"Id": "345af7a2-e432-48b8-a6ce-2acf0519882a",
"Name": "Bring PickUp Parcel",
"Carrier": "Bring",
"Price": 29, // 29.00 SEK
"ShippingFee": 2900, // 29.00 SEK
"Location": {
"Id": "74383",
"Name": "Agent name"
},
"Fields": [{"Id": "FCRECEIVERSMS", "Value": "070123456"}],
"Addons": [{"id":"FCNOTIFYPHONE","price":29,"fields":[{"id":"phone","value":"01234567"}]}],
"PostalCode": "99999"
}
}
},
"Customer": {
"Id": 1,
"NationalId": "121314-1234",
"CountryCode": "SE",
"IsCompany": false,
"IsVerified": false
},
"ShippingAddress": {
"FullName": "John Doe",
"FirstName": "John",
"LastName": "Doe",
"StreetAddress": "My Street 1",
"CoAddress": "",
"PostalCode": "99999",
"City": "My Town",
"CountryCode": "SE",
"IsGeneric": false,
"AddressLines": null
},
"BillingAddress": {
"FullName": "John Doe",
"FirstName": "John",
"LastName": "Doe",
"StreetAddress": "My Street 1",
"CoAddress": "",
"PostalCode": "99999",
"City": "My Town",
"CountryCode": "SE",
"IsGeneric": false,
"AddressLines": null
},
"Gui": {
"Layout": "desktop",
"Snippet": "<iframe src=\"\"></iframe>"
},
"Locale": "sv-SE",
"Currency": "SEK",
"CountryCode": "SE",
"ClientOrderNumber": "ABCDEFGHIJKLMNOP0123456789",
"OrderId": 1234567890,
"EmailAddress": "john.doe@svea.com",
"PhoneNumber": "070-1234567",
"PaymentType": "INVOICE",
"Payment": null,
"Status": "Final",
"CustomerReference": null,
"SveaWillBuyOrder": false,
"IdentityFlags": {
"HideNotYou": false,
"HideChangeAddress": true,
"HideAnonymous": true
},
"MerchantData": null,
"PeppolId": null,
"Recurring": true,
"RecurringToken": "d651c11e-984a-4a80-a2d5-c69fe38e10e0" //Token to be used for subsequent order, only avaliable when order has been finalized
}
Checkout Shipping
Checkout supports shipping. To enable the Shipping Checkout some additional information needs to be provided when creating an order. Merchant also needs to have nShift configured in order to utilize the Shipping checkout. See further details in the create order model CreateOrderModel how a successful request can be made. Currently not usable together if order has recurring flag set to true
Recurring Orders
To enable the use of Recurring Orders merchants need to have this feature activated. Please contact your sales contact for more information.
The feature will enable subscriptions and other recurring purchases through Checkout. Recurring orders are based on a unique token that is created when the first purchase is finalized. The token represents the customer and their chosen payment method which are used to initiate additional purchases.
For information about how to create recurring orders, see Creating a recurring order
Displaying the Checkout on your site
When an order is created using the CreateOrder endpoint, the response contains a code snippet that can be embedded on a page of your choice.
Snippet:
- React
- Razor
import { useCallback, useEffect, useRef, useState } from "react";
import "./App.css";
import axios from "axios";
export interface CreateOrderResponse {
OrderId: number;
Gui: Gui;
}
export interface Gui {
Snippet: string;
}
export const createCheckoutOrder = async () => {
// Replace "your-service.com/create-order" with your service
return axios.post<CreateOrderResponse>("your-service.com/create-order");
};
function App() {
const divRef = useRef<HTMLDivElement>(null);
const [checkoutSnippet, setCheckoutOrderSnippet] = useState<string>("");
const loadCheckoutOrder = useCallback(async () => {
const order = await createCheckoutOrder();
if (order.data?.Gui?.Snippet) {
setCheckoutOrderSnippet(order.data?.Gui?.Snippet);
}
}, [setCheckoutOrderSnippet]);
useEffect(() => {
loadCheckoutOrder();
}, [loadCheckoutOrder]);
// Since a custom script needs to be executed we must add the snippet via contextual fragment
useEffect(() => {
const fragment = document
.createRange()
.createContextualFragment(checkoutSnippet);
divRef.current!.replaceChildren(fragment);
}, [checkoutSnippet]);
return (
<>
<div>
<h1>Awesome E-Shop</h1>
<div ref={divRef} />
</div>
</>
);
}
export default App;
@model dynamic
<div>@Html.Raw(Model.Gui.Snippet)</div>
Result
Below is the result of successfully displaying the Svea Checkout widget on the website:
Receiving callbacks from Checkout
At certain points in an order's lifecycle, we will attempt to call endpoints on your side using the PushUri and CheckoutValidationCallBackUri. You provide these URI:s in the MerchantSettings when you call CreateOrder.
Valid callback URIs
Make sure that the URIs you provide are:
- Valid and accepted in your systems
- Can be resolved from outside your network
Be aware that the CheckoutValidationCallBackUri can be called multiple times for a single order.
Domain registrations
To be able to receive callbacks we require you to give us your domain names that will be used for callback and validation URIs. On initial contact with Svea you will be asked to provide domain names that you're will use. Any additional domain names should be reported to Webpay Support at support-webpay@svea.com. There is a set of invalid domain names that we don't allow to be used:
- *.local
- *.localhost
- *.example.com
- *.domain.com
- *.test
- *.loc
- *.local.se
- *.moc
- *.ngrcode
- *.me
- *.tld
Domains that are unreachable or mocked are not allowed.
Network rules
If you have a firewall blocking incoming requests, you must whitelist connections from Svea's IP ranges:
- 193.13.207.0/24
- 193.105.138.0/24
Age Limit
Currently available for Swedish, Norwegian and Finnish merchants. Only applied to B2C customers.
In order for having age requirements enabled, particularly minimum age, you may have to either enable it explicitly for your orders while creating them or apply it using a general setting for all of your orders to have the same requirements. However you always can override the rule through the API both using creation and updating the order given certain circumstances If age limit is required, we always ask for BankId authentication once the end customer identifies himself/herself, and Anonymous flow is forbidden as well.
You need to provide MinAge while creating order and it should be a positive integer, otherwise you may leave it as what it is, nothing should be changed on your end! For more information regarding enforcing age requirements, see validation
In case you need to impose the age requirement as a general setting for all your upcoming orders, please contact our support team
Client Libraries
Client library for PHP - https://github.com/sveawebpay/php-checkout