Guides
Foreign currency invoices and the NBP rate
An order can be in euro, dollars or another NBP table A currency. The invoice keeps the amounts in that currency and shows VAT in PLN at the NBP rate.
How it works
Set order.currency to a currency code, e.g. EUR. Line and shipping prices are in that currency. The invoice shows amounts in the order currency and the VAT amount also in PLN, converted at the NBP table A average rate of the last business day before the payment day (paid_at). The table number and the rate date are printed on the invoice.
curl -X POST https://app.ksefshop.pl/v1/invoices \
-H "Authorization: Bearer $KSEF_API_KEY" \
-H "Idempotency-Key: order-SO-1002" \
-H "Content-Type: application/json" \
-d '{
"order": {
"external_id": "SO-1002",
"paid_at": "2026-10-20T07:15:00Z",
"currency": "EUR",
"payment_method": "transfer",
"buyer": {
"nip": "7740001454",
"name": "Przykład S.A.",
"address_line1": "ul. Długa 5",
"address_line2": "80-831 Gdańsk"
},
"lines": [
{
"name": "Lampka biurkowa LED",
"quantity": 1,
"unit_price": "123.00",
"vat_rate": "23"
}
]
}
}'<?php
$payload = [
'order' => [
'external_id' => 'SO-1002',
'paid_at' => '2026-10-20T07:15:00Z',
'currency' => 'EUR',
'payment_method' => 'transfer',
'buyer' => [
'nip' => '7740001454',
'name' => 'Przykład S.A.',
'address_line1' => 'ul. Długa 5',
'address_line2' => '80-831 Gdańsk',
],
'lines' => [
[
'name' => 'Lampka biurkowa LED',
'quantity' => 1,
'unit_price' => '123.00',
'vat_rate' => '23',
],
],
],
];
$ch = curl_init('https://app.ksefshop.pl/v1/invoices');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('KSEF_API_KEY'),
'Idempotency-Key: order-SO-1002',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($payload, JSON_UNESCAPED_UNICODE),
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
$data = json_decode($body, true);
if ($status >= 400) {
throw new RuntimeException($data['error']['code'] . ': ' . $data['error']['message']);
}
echo var_export($data['id'], true), ' ', var_export($data['status'], true), PHP_EOL;const res = await fetch("https://app.ksefshop.pl/v1/invoices", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KSEF_API_KEY}`,
"Idempotency-Key": "order-SO-1002",
"Content-Type": "application/json",
},
body: JSON.stringify({
order: {
external_id: "SO-1002",
paid_at: "2026-10-20T07:15:00Z",
currency: "EUR",
payment_method: "transfer",
buyer: {
nip: "7740001454",
name: "Przykład S.A.",
address_line1: "ul. Długa 5",
address_line2: "80-831 Gdańsk",
},
lines: [
{ name: "Lampka biurkowa LED", quantity: 1, unit_price: "123.00", vat_rate: "23" },
],
},
}),
});
const data = await res.json();
if (!res.ok) throw new Error(`${data.error.code}: ${data.error.message}`);
console.log(data.id, data.status);import os
import requests
resp = requests.post(
"https://app.ksefshop.pl/v1/invoices",
headers={
"Authorization": f"Bearer {os.environ['KSEF_API_KEY']}",
"Idempotency-Key": "order-SO-1002",
},
json={
"order": {
"external_id": "SO-1002",
"paid_at": "2026-10-20T07:15:00Z",
"currency": "EUR",
"payment_method": "transfer",
"buyer": {
"nip": "7740001454",
"name": "Przykład S.A.",
"address_line1": "ul. Długa 5",
"address_line2": "80-831 Gdańsk",
},
"lines": [
{
"name": "Lampka biurkowa LED",
"quantity": 1,
"unit_price": "123.00",
"vat_rate": "23",
},
],
},
},
timeout=30,
)
data = resp.json()
if not resp.ok:
raise RuntimeError(f"{data['error']['code']}: {data['error']['message']}")
print(data["id"], data["status"])Which currencies
PLN and every currency the NBP publishes in table A of average rates (EUR, USD, GBP, CHF, CZK and more). A currency outside table A returns 400 currency_not_supported.
Check the rate before sending
You can check the rate and the VAT conversion by hand in our free tool: NBP rate for an invoice. It calculates the same way: table A of the business day before the given date.
Watch out
paid_atdecides the rate date. Send the real payment time, not the time you call the API.total_grossof the invoice object is in the invoice currency, not in PLN.- A correction of a foreign currency invoice uses the same currency as the original.