> This page is for API Reference.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.navipartner.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.navipartner.com/_mcp/server.

# Create Payment Line

POST https://api.npretail.app/{tenant}/{environment}/{company}/pos/sale/{saleId}/paymentline/{paymentLineId}
Content-Type: application/json

Creates a cash payment line or records an externally processed EFT attempt. Provide a unique GUID for paymentLineId.
Returns HTTP 201 with the saleId, refreshed entities and sale totals.

For EFT, send success: true for an already authorized payment. BC records the EFT Transaction Request and creates an approved POS payment line with the supplied paymentLineId.
A successful zero-amount attempt also creates a line, but has no financial impact.
An EFT request using a paymentLineId already used by any active POS sale line returns HTTP 400 without adding another EFT request, payment line or receipt. This rejects the duplicate; it does not replay the original success response.

New EFT integrations must send success as a JSON boolean. For backwards compatibility, omitted success is accepted and treated as false. An explicitly supplied non-boolean value returns HTTP 400 without recording an attempt or payment.
Identifier values exceeding the documented length limits also return HTTP 400 without recording an attempt or payment.
If success is false or omitted, BC records the attempted amount and supplied PSP reference, card data, PAR and receipts without creating a POS payment line.
The EFT output and result amounts are zero. The response has an empty refreshedPaymentLines array and an unchanged totalPaymentAmount.
GET for that paymentLineId returns 404. Repeating a failed request can create additional EFT audit records; these requests are not deduplicated.
Earlier behavior added the amount to the sale even when success was false or omitted. Callers must send success: true for authorized payments to count toward completing the sale; the compatibility default does not pay the sale.

EFT amounts use the G/L Setup local currency. BC uses the time it receives the request, converted to the API session's local time zone, for the transaction and stored receipt date/time.
Only LCY EFT payments are supported. Configure the EFT payment method for LCY, as for staffed POS; the API uses the same POS payment-line insertion without API-specific currency conversion.
The payload does not supply the provider's authorization timestamp or test/production mode.
Negative EFT amounts return HTTP 400 with the message "refunds not implemented" and create no records. Cash amount handling is unchanged.

Reference: https://docs.navipartner.com/apis/api-reference/pos/possale/create-pos-payment-line

## Authentication

- `x-np-api-key` header (required) — API Key authentication via header

## Request

### Path parameters

- `tenant` (string, required) — Your Entra Tenant ID. [More details.](/paths#1-tenant)
- `environment` (string, required) — Your Business Central Environment. [More details.](/paths#2-environment)
- `company` (string, required) — Your Business Central Company. [More details.](/paths#3-company)
- `saleId` (UUID, required) — The id of a POS sale. This can be provided by the API consumer when creating a new sale.
- `paymentLineId` (UUID, required) — The id of a payment line within a POS sale.

### Body (application/json)

This endpoint expects a CreatePOSPaymentLine.

- `paymentMethodCode` (string, required) — POS payment method code, at most 10 characters. Overlong codes are rejected, not truncated.
- `paymentType` (enum, required) — Type of payment (Cash or EFT)
  - Allowed values: `Cash`, `EFT`
- `amount` (double, required) — For EFT, the attempted amount in the G/L Setup local currency. Negative EFT amounts fail with "refunds not implemented".
- `description` (string, optional)
- `maskedCardNo` (string, optional) — For EFT payments, masked card number, at most 30 characters. Overlong values are rejected, not truncated.
- `pspReference` (string, optional) — For EFT payments, PSP reference number, at most 16 characters. Overlong values are rejected, not truncated.
- `parToken` (string, optional) — For EFT payments, the Payment Account Reference, or PAR, identifying the payment account. At most 100 characters, stored in the dedicated Payment Account Reference field; overlong values are rejected, not truncated. This is not a reusable authorization token and is not stored as an External Payment Token.
- `cardApplicationId` (string, optional) — For EFT payments, card application ID for payment method mapping, at most 32 characters. Overlong values are rejected, not truncated.
- `success` (boolean, optional) — Required for new EFT integrations and must be a JSON boolean when supplied. Non-boolean values return HTTP 400. Not required for Cash. Send true only when the external provider has authorized the payment. True creates an approved POS payment line; false records the failed attempt without a POS payment line and does not increase the sale's payment total. For backwards compatibility, omitting success is accepted and treated as false.
- `eftReceipt` (list of string, optional) — For EFT payments, receipt lines to store for either a successful or failed attempt.

## Response

### 201

- `saleId` (UUID, required) — The id of a POS sale. This can be provided by the API consumer when creating a new sale.
- `receiptNo` (string, required)
- `posUnit` (string, required)
- `posStore` (string, required)
- `date` (date, required)
- `startTime` (datetime, required)
- `customerNo` (string, required)
- `salespersonCode` (string, required)
- `vatBusinessPostingGroup` (string, required)
- `genBusinessPostingGroup` (string, required)
- `refreshedSaleLines` (list of POSSaleLineResponse, required) — Full objects for all sale lines that were created or modified
- `refreshedPaymentLines` (list of POSPaymentLineResponse, required) — Full objects for all payment lines that were created or modified
- `deletedSaleLines` (list of string, required) — Array of SystemIds (UUIDs) for sale lines that were deleted
- `deletedPaymentLines` (list of string, required) — Array of SystemIds (UUIDs) for payment lines that were deleted
- `totalSalesAmountInclVat` (double, required) — Total amount of all sale lines including VAT
- `totalPaymentAmount` (double, required) — Total amount of all payment lines

## Types

### POSSaleLineResponse

A sale line in the response

- `id` (UUID, required) — The id of a sale line within a POS sale.
- `sortKey` (integer, required)
- `type` (enum, required)
  - Allowed values: `Item`, `Item Category`, `BOM List`, `Customer Deposit`, `Comment`, `Rounding`, `G/L Payment`, `Issue Voucher`
- `code` (string, required)
- `variantCode` (string, required)
- `description` (string, required)
- `quantity` (double, required)
- `unitPrice` (double, required)
- `discountPct` (double, required)
- `discountAmount` (double, required)
- `vatPercent` (double, required)
- `amountInclVat` (double, required)
- `amount` (double, required)
- `unitOfMeasure` (string, required)
- `isAddon` (boolean, required) — Whether this line is an addon to another item
- `description2` (string, optional)
- `appliesToLine` (UUID, optional) — If this is an addon, the SystemId of the parent line it applies to
- `deleted` (boolean, optional)

### POSPaymentLineResponse

A payment line in the response

- `id` (UUID, required) — The id of a payment line within a POS sale.
- `sortKey` (integer, required)
- `paymentMethodCode` (string, required)
- `description` (string, required)
- `amountInclVat` (double, required)
- `deleted` (boolean, optional)

## Examples

**Request**

```json
{
  "paymentMethodCode": "CASH",
  "paymentType": "Cash",
  "amount": 100,
  "description": "Cash payment"
}
```

**Response**

```json
{
  "saleId": "bcc8ec51-906b-4a57-9680-1d120dd55b01",
  "receiptNo": "12345678",
  "posUnit": "QR_FOOD_APP",
  "posStore": "STORE01",
  "date": "2024-01-01",
  "startTime": "2024-01-01T17:00:00Z",
  "customerNo": "C12345",
  "salespersonCode": "SP001",
  "vatBusinessPostingGroup": "DOMESTIC",
  "genBusinessPostingGroup": "DOMESTIC",
  "refreshedSaleLines": [],
  "refreshedPaymentLines": [
    {
      "id": "374a4076-52b8-f011-a901-904652264ae4",
      "sortKey": 20000,
      "paymentMethodCode": "CASH",
      "description": "Cash Payment",
      "amountInclVat": 18.5
    }
  ],
  "deletedSaleLines": [],
  "deletedPaymentLines": [],
  "totalSalesAmountInclVat": 125,
  "totalPaymentAmount": 18.5
}
```

**SDK Code**

```python
import requests

url = "https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816"

payload = {
    "paymentMethodCode": "CASH",
    "paymentType": "Cash",
    "amount": 100,
    "description": "Cash payment"
}
headers = {
    "x-np-api-key": "<NaviPartner API Key>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816';
const options = {
  method: 'POST',
  headers: {'x-np-api-key': '<NaviPartner API Key>', 'Content-Type': 'application/json'},
  body: '{"paymentMethodCode":"CASH","paymentType":"Cash","amount":100,"description":"Cash payment"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816"

	payload := strings.NewReader("{\n  \"paymentMethodCode\": \"CASH\",\n  \"paymentType\": \"Cash\",\n  \"amount\": 100,\n  \"description\": \"Cash payment\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("x-np-api-key", "<NaviPartner API Key>")
	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
require 'uri'
require 'net/http'

url = URI("https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["x-np-api-key"] = '<NaviPartner API Key>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"paymentMethodCode\": \"CASH\",\n  \"paymentType\": \"Cash\",\n  \"amount\": 100,\n  \"description\": \"Cash payment\"\n}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816")
  .header("x-np-api-key", "<NaviPartner API Key>")
  .header("Content-Type", "application/json")
  .body("{\n  \"paymentMethodCode\": \"CASH\",\n  \"paymentType\": \"Cash\",\n  \"amount\": 100,\n  \"description\": \"Cash payment\"\n}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816', [
  'body' => '{
  "paymentMethodCode": "CASH",
  "paymentType": "Cash",
  "amount": 100,
  "description": "Cash payment"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'x-np-api-key' => '<NaviPartner API Key>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816");
var request = new RestRequest(Method.POST);
request.AddHeader("x-np-api-key", "<NaviPartner API Key>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"paymentMethodCode\": \"CASH\",\n  \"paymentType\": \"Cash\",\n  \"amount\": 100,\n  \"description\": \"Cash payment\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "x-np-api-key": "<NaviPartner API Key>",
  "Content-Type": "application/json"
]
let parameters = [
  "paymentMethodCode": "CASH",
  "paymentType": "Cash",
  "amount": 100,
  "description": "Cash payment"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.npretail.app/01234567-89ab-cdef-0123-456789abcdef/production/CRONUS%2520International%2520Ltd./pos/sale/0d200aa6-aacd-4b78-b673-c4fb7461f5ea/paymentline/80c340c5-00ce-46c5-8a32-8736e59b7816")! 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()
```