> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.crisscross.money/api-reference/collect/payments/payment-initiation/create-checkout-session/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.crisscross.money/_mcp/server. # Create Checkout Session POST https://api.crisscross.money/v1/checkout/session Content-Type: application/json Creates a checkout session. For hosted integrations (`integrationType: hosted`) the response includes a signed hosted-checkout `paymentLink`; direct integrations receive identifiers only — no `paymentLink` — and initiate the payment against the returned `sessionId` via `POST /payment`. Reference: https://docs.crisscross.money/api-reference/collect/payments/payment-initiation/create-checkout-session ## Request ### Body (application/json) This endpoint expects a CreateCheckoutSessionRequest. - `merchantId` (string, required) — The merchant identifier. - `merchantReference` (string, required) — Your reference for the checkout session. **Unique per merchant** — reusing a reference is rejected with `409 DUPLICATE_REFERENCE` carrying the existing session's id. Use a unique value per logical order; retrying a request with the same reference is a safe probe for whether the original creation succeeded. Always supply a non-empty value: an empty string is accepted, but it is exempt from the uniqueness check and the session cannot be found via Search Payments. See the [Payment Status & Recovery guide](/collect/payment-recovery). - `amount` (integer, required) — Amount in minor units, denominated in `currency` (the initiation currency). - `currency` (enum, required) — Currency of the session (ISO 4217). Without a `rateLockId` this is the collection currency the payer pays in. With a `rateLockId` it must equal the lock's base currency (the currency you price in, e.g. `USD`); the payer is then charged the equivalent in the lock's quote currency at the lock's all-in rate. - Allowed values: `ZAR`, `NGN`, `UGX`, `ZMW`, `GHS`, `KES`, `TZS`, `ETB`, `USD`, `XAF`, `XOF`, `SLE` - `integrationType` (enum, required) — Type of integration. - Allowed values: `hosted`, `direct` - `payerDetails` (CreateCheckoutSessionPayerDetails, required) - `collectionCurrency` (enum, optional) — Optional. The **collection currency** — the currency the payer is actually charged in. Defaults to the primary currency for `payerDetails.location` when omitted. When `collectionCurrency` differs from `currency`, [Adaptive Currency Conversion](/adaptive-currency-conversion) applies: priced by the supplied `rateLockId`, or by its default per-session quote minted at session creation. - Allowed values: `ZAR`, `NGN`, `UGX`, `ZMW`, `GHS`, `KES`, `TZS`, `ETB`, `USD`, `XAF`, `XOF`, `SLE` - `redirectUrl` (string, optional) — Optional URL to redirect after payment. - `rateLockId` (string, optional) — Optional rate lock to apply to this session. When set, the session `currency` must equal the lock's base currency, the session's collection currency must equal the lock's quote currency, and the payer is charged the equivalent in the lock's quote currency at the lock's all-in rate. The lock is verified at session creation and again when a payment is initiated; a lock that is unknown, expired, or cancelled is rejected with `422`. If omitted and `collectionCurrency` differs from `currency`, the conversion falls back to [Adaptive Currency Conversion](/adaptive-currency-conversion)'s default per-session rate. - `paymentAttributes` (map from string to string, optional) — Optional session attributes to pass through the payment lifecycle. All values must be strings. Three keys are meaningful to the hosted checkout — `showChargedAs`, `showConversionRate` and `showConversionFee` — each defaulting to shown and accepting `"false"` to hide that line from the payer. - `expiresInSeconds` (integer, optional) — Optional session lifetime in seconds (30 seconds to 7 days). The payment confirmation window expires this long after creation; defaults to the standard session lifetime when omitted. ## Response ### 201 Session created successfully. When the session was priced by a [rate lock](/rate-locks), the response also carries `fxCommit` — the collection currency and amount the payer will be charged, the all-in rate, the markup, and the fee — so you can show the payer both amounts without a second call. A session priced by the default per-session rate returns identifiers only; read it back with [Get Checkout Session](#operation/getCheckoutSession) to see its `fxCommit`. - `sessionId` (string, required) — Unique identifier for the session. - `paymentLink` (string, optional) — The hosted checkout URL for this session, present when `integrationType` is `hosted`. Redirect the buyer to it exactly as returned — the `signature` query parameter authorises the session, so a URL rebuilt by hand will not authenticate. - `payerId` (string, optional) — Persistent identifier for the payer (customer). CrissCross assigns one when the session is created, or returns the existing `payerId` if you supplied one in `payerDetails.payerId`. Store it against your customer record to recognise this customer on future sessions. See the [Payer ID guide](/payer-id). - `signature` (string, optional) — HMAC that authorises this session on the hosted checkout. It is already appended to `paymentLink` as a `signature` query parameter, so for a hosted integration you do not need to handle it separately — redirect the buyer to `paymentLink` as returned. Treat it as a capability for this one session: anyone holding it can act on the session, so do not log it or expose it beyond the buyer's browser. Unrelated to the `svix-signature` header used to verify [webhooks](/core-concepts-webhooks). - `fxCommit` (FxCommit, optional) — Present when the session was priced by a [rate lock](/rate-locks) (`rateLockId` supplied): the collection currency and amount the payer will be charged at the lock's `allInRate`, with `pricingModel: RATE_LOCK` and `quoteId` the `rlk_` lock id. Absent for same-currency sessions and for sessions priced by the default per-session rate. ## Errors ### 400 Bad Request Error Invalid request parameters. Also returned when your account prices Adaptive Currency Conversion with rate locks and the session carries no `rateLockId` — every converted session must bring one. - `message` (string, required) — Human-readable description of what went wrong. - `error` (string, required) — Error category. Most endpoints return the HTTP reason phrase (e.g. "Bad Request", "Unauthorized", "Conflict", "Unprocessable Entity", "Internal Server Error"). Some return a machine-readable snake_case code instead — notably the FX and rate-lock rejections on checkout session creation and payment initiation, where several distinct codes share a single HTTP status. Where a code is present it is the finer discriminator and is safe to branch on. - `statusCode` (integer, required) — HTTP status code, mirroring the response header. The response header is the source of truth. ### 401 Unauthorized Error Unauthorized. - `message` (string, required) — Human-readable description of what went wrong. - `error` (string, required) — Error category. Most endpoints return the HTTP reason phrase (e.g. "Bad Request", "Unauthorized", "Conflict", "Unprocessable Entity", "Internal Server Error"). Some return a machine-readable snake_case code instead — notably the FX and rate-lock rejections on checkout session creation and payment initiation, where several distinct codes share a single HTTP status. Where a code is present it is the finer discriminator and is safe to branch on. - `statusCode` (integer, required) — HTTP status code, mirroring the response header. The response header is the source of truth. ### 403 Forbidden Error FX at checkout is not enabled on your account. Returned when the session would require a currency conversion — the session `currency` differs from the collection currency for the payer's location — and the feature has not been switched on for you. This check runs before any rate-lock handling, so while it is failing no rate-lock error can be reached, whatever `rateLockId` you send. Contact us to have FX at checkout enabled; see [Adaptive Currency Conversion](/adaptive-currency-conversion). - `message` (string, required) — Human-readable description of what went wrong. - `error` (string, required) — Error category. Most endpoints return the HTTP reason phrase (e.g. "Bad Request", "Unauthorized", "Conflict", "Unprocessable Entity", "Internal Server Error"). Some return a machine-readable snake_case code instead — notably the FX and rate-lock rejections on checkout session creation and payment initiation, where several distinct codes share a single HTTP status. Where a code is present it is the finer discriminator and is safe to branch on. - `statusCode` (integer, required) — HTTP status code, mirroring the response header. The response header is the source of truth. ### 409 Conflict Error Conflict — a session with this `merchantReference` already exists for this merchant. `existingSessionId` is the most recent session owning the reference; fetch its state with `GET /checkout/session?sessionId={existingSessionId}`. See the [Payment Status & Recovery guide](/collect/payment-recovery). - `code` (enum, required) — Machine-readable conflict code. - Allowed values: `DUPLICATE_REFERENCE` - `message` (string, required) — Error message describing what went wrong. - `existingSessionId` (string, required) — Id of the most recent session owning this merchantReference. ### 422 Unprocessable Entity Error Unprocessable Entity. When a `rateLockId` is supplied, the lock is verified at session creation: an unknown lock, one that has expired or been cancelled, a base currency not matching the session `currency`, or a quote currency not matching the session's collection currency is rejected here. The lock is verified again when a payment is initiated. All four rejections below share `422` — branch on `error`, not on the status. The lock is checked in order: it must exist, then its currencies must match the session, then it must still be usable. A currency mismatch is therefore reported before expiry is even evaluated. - `message` (string, required) — Human-readable description of what went wrong. - `error` (string, required) — Error category. Most endpoints return the HTTP reason phrase (e.g. "Bad Request", "Unauthorized", "Conflict", "Unprocessable Entity", "Internal Server Error"). Some return a machine-readable snake_case code instead — notably the FX and rate-lock rejections on checkout session creation and payment initiation, where several distinct codes share a single HTTP status. Where a code is present it is the finer discriminator and is safe to branch on. - `statusCode` (integer, required) — HTTP status code, mirroring the response header. The response header is the source of truth. ### 502 Bad Gateway Error The rate-lock service could not be reached. Transient — retry with backoff. This is an upstream failure, not a problem with your request or your lock. - `message` (string, required) — Human-readable description of what went wrong. - `error` (string, required) — Error category. Most endpoints return the HTTP reason phrase (e.g. "Bad Request", "Unauthorized", "Conflict", "Unprocessable Entity", "Internal Server Error"). Some return a machine-readable snake_case code instead — notably the FX and rate-lock rejections on checkout session creation and payment initiation, where several distinct codes share a single HTTP status. Where a code is present it is the finer discriminator and is safe to branch on. - `statusCode` (integer, required) — HTTP status code, mirroring the response header. The response header is the source of truth. ## Types ### CreateCheckoutSessionPayerDetails - `emailAddress` (string, required) — Email address of the payer, used for receipts and provider records. - `location` (enum, required) — Country code of the payer (alpha-3). - Allowed values: `ZAF`, `NGA`, `UGA`, `ZMB`, `GHA`, `KEN`, `TZA`, `ETH`, `CMR`, `SEN`, `BEN`, `BFA`, `CIV`, `MLI`, `TGO`, `SLE` - `fullName` (string, optional) — Full name of the payer. - `phoneNumber` (string, optional) — Phone number of the payer. - `payerId` (string, optional) — Optional. The `payerId` of an existing customer, used to associate this session with a payer you've seen before. Supply the `payerId` you stored from a previous session's response. Omit it for a new customer — CrissCross will assign one and return it. See the [Payer ID guide](/payer-id). ### FxCommit Immutable FX conversion snapshot recorded when a session or transaction is priced in a currency other than the merchant's initiation currency. Written whenever [Adaptive Currency Conversion](/adaptive-currency-conversion) applies — priced per session by default, or by a [rate lock](/rate-locks). - `quoteId` (string, required) — Identifier of the FX commitment that priced this conversion. For a session priced by a [rate lock](/rate-locks) this is the `rlk_` rate lock id — use it to read back which lock a session was priced against. For an ACC conversion it is the upstream quote identifier, preserved for audit. - `collectionCurrency` (string, required) — ISO 4217 currency code the customer pays in. - `collectionAmount` (string, required) — All-in amount the customer is asked to pay, in `collectionCurrency` major units (decimal string). - `midRate` (string, required) — Spot mid-market rate before markup. `1 initiation-currency = midRate collection-currency` (decimal string, 8 decimal places). - `markupBps` (integer, required) — Markup applied over the mid rate, in basis points (100 bps = 1%). - `allInRate` (string, required) — The rate actually transacted at — `midRate * (1 + markupBps / 10000)` (decimal string, 8 decimal places). - `fee` (string, required) — Markup component denominated in `collectionCurrency`, expressed as a major-unit decimal string. - `expiresAt` (datetime, required) — RFC3339 timestamp. The commit is valid until this time; past-expiry payment submissions are rejected `422` (stale quote) and the hosted page refreshes the rate. - `pricingModel` (enum, optional) — Which [Adaptive Currency Conversion](/adaptive-currency-conversion) flow priced the session — `SPOT_QUOTE` for the default [per-session rate](/api-reference/collect/per-session), `RATE_LOCK` for an attached [rate lock](/rate-locks). May be absent on sessions created before this field was introduced. - Allowed values: `SPOT_QUOTE`, `RATE_LOCK` ## Examples ### Hosted checkout **Response** ```json { "sessionId": "0d3f1d6c-1c49-4b89-9db6-1fdc06f24c8a", "paymentLink": "https://checkout.payos.money/session/0d3f1d6c-1c49-4b89-9db6-1fdc06f24c8a?signature=kRe8vQZ2mXpL7nT4wYbHs1JdA0uCgFiO6ExNq3ZrPyM", "payerId": "2a1c4f1a-0d44-4f16-8c8e-9a3b4c5d6e7f", "signature": "kRe8vQZ2mXpL7nT4wYbHs1JdA0uCgFiO6ExNq3ZrPyM" } ``` **SDK Code** ```python Hosted checkout import requests url = "https://api.crisscross.money/v1/checkout/session" response = requests.post(url) print(response.json()) ``` ```javascript Hosted checkout const url = 'https://api.crisscross.money/v1/checkout/session'; const options = {method: 'POST'}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go Hosted checkout package main import ( "fmt" "net/http" "io" ) func main() { url := "https://api.crisscross.money/v1/checkout/session" req, _ := http.NewRequest("POST", url, nil) res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby Hosted checkout require 'uri' require 'net/http' url = URI("https://api.crisscross.money/v1/checkout/session") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) response = http.request(request) puts response.read_body ``` ```java Hosted checkout import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.crisscross.money/v1/checkout/session") .asString(); ``` ```php Hosted checkout request('POST', 'https://api.crisscross.money/v1/checkout/session'); echo $response->getBody(); ``` ```csharp Hosted checkout using RestSharp; var client = new RestClient("https://api.crisscross.money/v1/checkout/session"); var request = new RestRequest(Method.POST); IRestResponse response = client.Execute(request); ``` ```swift Hosted checkout import Foundation let request = NSMutableURLRequest(url: NSURL(string: "https://api.crisscross.money/v1/checkout/session")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` ### Direct integration — priced by a rate lock **Response** ```json { "sessionId": "01951c8a-7c3d-7e1f-9d4a-2b3c4d5e6f70", "payerId": "2a1c4f1a-0d44-4f16-8c8e-9a3b4c5d6e7f", "fxCommit": { "quoteId": "rlk_550e8400-e29b-41d4-a716-446655440000", "collectionCurrency": "KES", "collectionAmount": "13260.00", "midRate": "130.00", "markupBps": 200, "allInRate": "132.60", "fee": "260.00", "expiresAt": "2026-06-24T22:30:00Z", "pricingModel": "RATE_LOCK" } } ``` **SDK Code** ```python Direct integration — priced by a rate lock import requests url = "https://api.crisscross.money/v1/checkout/session" response = requests.post(url) print(response.json()) ``` ```javascript Direct integration — priced by a rate lock const url = 'https://api.crisscross.money/v1/checkout/session'; const options = {method: 'POST'}; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go Direct integration — priced by a rate lock package main import ( "fmt" "net/http" "io" ) func main() { url := "https://api.crisscross.money/v1/checkout/session" req, _ := http.NewRequest("POST", url, nil) res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby Direct integration — priced by a rate lock require 'uri' require 'net/http' url = URI("https://api.crisscross.money/v1/checkout/session") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) response = http.request(request) puts response.read_body ``` ```java Direct integration — priced by a rate lock import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.crisscross.money/v1/checkout/session") .asString(); ``` ```php Direct integration — priced by a rate lock request('POST', 'https://api.crisscross.money/v1/checkout/session'); echo $response->getBody(); ``` ```csharp Direct integration — priced by a rate lock using RestSharp; var client = new RestClient("https://api.crisscross.money/v1/checkout/session"); var request = new RestRequest(Method.POST); IRestResponse response = client.Execute(request); ``` ```swift Direct integration — priced by a rate lock import Foundation let request = NSMutableURLRequest(url: NSURL(string: "https://api.crisscross.money/v1/checkout/session")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ``` ### Payment Initiation_createCheckoutSession_example **Request** ```json { "merchantId": "1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "merchantReference": "ORDER12345", "amount": 15000, "currency": "NGN", "integrationType": "hosted", "payerDetails": { "emailAddress": "chinwe.okafor@example.com", "location": "NGA", "fullName": "Chinwe Okafor", "phoneNumber": "08012345678" }, "redirectUrl": "https://merchant.com/redirect", "paymentAttributes": { "orderId": "ORDER12345" } } ``` **Response** ```json { "sessionId": "0d3f1d6c-1c49-4b89-9db6-1fdc06f24c8a", "paymentLink": "https://checkout.payos.money/session/0d3f1d6c-1c49-4b89-9db6-1fdc06f24c8a?signature=kRe8vQZ2mXpL7nT4wYbHs1JdA0uCgFiO6ExNq3ZrPyM", "payerId": "2a1c4f1a-0d44-4f16-8c8e-9a3b4c5d6e7f", "signature": "kRe8vQZ2mXpL7nT4wYbHs1JdA0uCgFiO6ExNq3ZrPyM" } ``` **SDK Code** ```python Payment Initiation_createCheckoutSession_example import requests url = "https://api.crisscross.money/v1/checkout/session" payload = { "merchantId": "1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "merchantReference": "ORDER12345", "amount": 15000, "currency": "NGN", "integrationType": "hosted", "payerDetails": { "emailAddress": "chinwe.okafor@example.com", "location": "NGA", "fullName": "Chinwe Okafor", "phoneNumber": "08012345678" }, "redirectUrl": "https://merchant.com/redirect", "paymentAttributes": { "orderId": "ORDER12345" } } headers = {"Content-Type": "application/json"} response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript Payment Initiation_createCheckoutSession_example const url = 'https://api.crisscross.money/v1/checkout/session'; const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"merchantId":"1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d","merchantReference":"ORDER12345","amount":15000,"currency":"NGN","integrationType":"hosted","payerDetails":{"emailAddress":"chinwe.okafor@example.com","location":"NGA","fullName":"Chinwe Okafor","phoneNumber":"08012345678"},"redirectUrl":"https://merchant.com/redirect","paymentAttributes":{"orderId":"ORDER12345"}}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go Payment Initiation_createCheckoutSession_example package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.crisscross.money/v1/checkout/session" payload := strings.NewReader("{\n \"merchantId\": \"1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n \"merchantReference\": \"ORDER12345\",\n \"amount\": 15000,\n \"currency\": \"NGN\",\n \"integrationType\": \"hosted\",\n \"payerDetails\": {\n \"emailAddress\": \"chinwe.okafor@example.com\",\n \"location\": \"NGA\",\n \"fullName\": \"Chinwe Okafor\",\n \"phoneNumber\": \"08012345678\"\n },\n \"redirectUrl\": \"https://merchant.com/redirect\",\n \"paymentAttributes\": {\n \"orderId\": \"ORDER12345\"\n }\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby Payment Initiation_createCheckoutSession_example require 'uri' require 'net/http' url = URI("https://api.crisscross.money/v1/checkout/session") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["Content-Type"] = 'application/json' request.body = "{\n \"merchantId\": \"1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n \"merchantReference\": \"ORDER12345\",\n \"amount\": 15000,\n \"currency\": \"NGN\",\n \"integrationType\": \"hosted\",\n \"payerDetails\": {\n \"emailAddress\": \"chinwe.okafor@example.com\",\n \"location\": \"NGA\",\n \"fullName\": \"Chinwe Okafor\",\n \"phoneNumber\": \"08012345678\"\n },\n \"redirectUrl\": \"https://merchant.com/redirect\",\n \"paymentAttributes\": {\n \"orderId\": \"ORDER12345\"\n }\n}" response = http.request(request) puts response.read_body ``` ```java Payment Initiation_createCheckoutSession_example import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.crisscross.money/v1/checkout/session") .header("Content-Type", "application/json") .body("{\n \"merchantId\": \"1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n \"merchantReference\": \"ORDER12345\",\n \"amount\": 15000,\n \"currency\": \"NGN\",\n \"integrationType\": \"hosted\",\n \"payerDetails\": {\n \"emailAddress\": \"chinwe.okafor@example.com\",\n \"location\": \"NGA\",\n \"fullName\": \"Chinwe Okafor\",\n \"phoneNumber\": \"08012345678\"\n },\n \"redirectUrl\": \"https://merchant.com/redirect\",\n \"paymentAttributes\": {\n \"orderId\": \"ORDER12345\"\n }\n}") .asString(); ``` ```php Payment Initiation_createCheckoutSession_example request('POST', 'https://api.crisscross.money/v1/checkout/session', [ 'body' => '{ "merchantId": "1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "merchantReference": "ORDER12345", "amount": 15000, "currency": "NGN", "integrationType": "hosted", "payerDetails": { "emailAddress": "chinwe.okafor@example.com", "location": "NGA", "fullName": "Chinwe Okafor", "phoneNumber": "08012345678" }, "redirectUrl": "https://merchant.com/redirect", "paymentAttributes": { "orderId": "ORDER12345" } }', 'headers' => [ 'Content-Type' => 'application/json', ], ]); echo $response->getBody(); ``` ```csharp Payment Initiation_createCheckoutSession_example using RestSharp; var client = new RestClient("https://api.crisscross.money/v1/checkout/session"); var request = new RestRequest(Method.POST); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"merchantId\": \"1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d\",\n \"merchantReference\": \"ORDER12345\",\n \"amount\": 15000,\n \"currency\": \"NGN\",\n \"integrationType\": \"hosted\",\n \"payerDetails\": {\n \"emailAddress\": \"chinwe.okafor@example.com\",\n \"location\": \"NGA\",\n \"fullName\": \"Chinwe Okafor\",\n \"phoneNumber\": \"08012345678\"\n },\n \"redirectUrl\": \"https://merchant.com/redirect\",\n \"paymentAttributes\": {\n \"orderId\": \"ORDER12345\"\n }\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift Payment Initiation_createCheckoutSession_example import Foundation let headers = ["Content-Type": "application/json"] let parameters = [ "merchantId": "1b2a3d4c-5e6f-7a8b-9c0d-1e2f3a4b5c6d", "merchantReference": "ORDER12345", "amount": 15000, "currency": "NGN", "integrationType": "hosted", "payerDetails": [ "emailAddress": "chinwe.okafor@example.com", "location": "NGA", "fullName": "Chinwe Okafor", "phoneNumber": "08012345678" ], "redirectUrl": "https://merchant.com/redirect", "paymentAttributes": ["orderId": "ORDER12345"] ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.crisscross.money/v1/checkout/session")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```