Skip to content
KSeF Kit

What Customer Data to Collect in Stripe to File to KSeF

Stripe collects the customer data and computes tax (Stripe Tax); KSeF Kit turns it into an FA(3) and files it to KSeF. Two fields drive the VAT treatment: customer_address.country and the buyer's tax id. From every customer, collect: whether it is a business (a valid tax id), the legal name, the country (most important), a full address, and the VAT/NIP. A missing or wrong number silently turns a B2B invoice into B2C — and that is not filed to KSeF.

What actually drives the VAT treatment

KSeF Kit picks the treatment from customer_address.country and the buyer's tax ids (customer_tax_ids):

Decision matrix: customer × location → treatment → data

Customer + location Treatment What to collect
Business + PL 23% domestic, to KSeF name, address, NIP
Business + other EU reverse charge (0%/np.), to KSeF name, address, prefixed EU VAT no., country; invoice marked "reverse charge / odwrotne obciążenie"
Business + non-EU outside EU VAT scope (e.g. art. 28b), to KSeF name, address, country, local tax id; watch foreign GST/VAT registration
Consumer + PL 23% name, address
Consumer + other EU customer-country VAT via OSS address + 2 non-contradictory location evidences; the €10,000 threshold; outside KSeF
Consumer + non-EU outside EU VAT scope / 0% address, country; outside KSeF

The consumer rows do not go to KSeF — KSeF Kit files B2B.

The minimum data set for every customer

How to collect it in Stripe Checkout

In Stripe Checkout, enable address, tax-id and automatic-tax collection. The crucial piece is customer_update — without it, Checkout data is not persisted to the Customer:

Stripe::Checkout::Session.create(
  mode: "payment",
  line_items: [ { price: price_id, quantity: 1 } ],
  billing_address_collection: "required",
  tax_id_collection: { enabled: true, required: "if_supported" },
  automatic_tax: { enabled: true },
  customer_update: { name: "auto", address: "auto" } # without this, data is not persisted
)

Creating a customer directly

When you create a customer outside Checkout, pass the name, address and tax id up front:

Stripe::Customer.create(
  name: "Example Buyer Ltd",
  address: { line1: "1 Example St", city: "Warsaw", postal_code: "00-001", country: "PL" },
  tax_id_data: [ { type: "pl_nip", value: "1111111111" } ]
)

pl_nip is version-gated. It needs API version 2026-01-28.clover+ and stripe-ruby ≥ 18.2.0. On older versions, store Polish companies as eu_vat (PL…) and strip the PL prefix when you build the FA(3).

Stripe through the Pay gem

The Pay gem forwards name and address via stripe_attributes (a method/lambda returning {name:, address:}). It passes automatic_tax and Checkout params through payment_processor.checkout(...) / .subscribe(...). Pay has no tax-id wrapper — pass tax_id_data via stripe_attributes, or use payment_processor.api_record and the native Stripe tax-id API:

class User < ApplicationRecord
  pay_customer stripe_attributes: :stripe_attributes

  def stripe_attributes(_pay_customer)
    {
      name: company_name,
      address: { line1: address_line1, city: city, postal_code: postal_code, country: country },
      tax_id_data: [ { type: "eu_vat", value: vat_number } ] # Pay won't wrap tax-ids itself
    }
  end
end

Validation: Stripe checks format, KSeF needs more

Stripe validates format only — not legal validity. For KSeF that is not enough. KSeF Kit also:

Professional advice is warranted. Some cases are genuinely nuanced: reverse charge without a confirmed VAT number, the €10,000 OSS threshold, and the need for foreign VAT/GST registration when selling outside the EU. These are tax decisions, not just technical ones.

Selling globally through Stripe?

Once the data in Stripe is complete, KSeF Kit recognises the transaction type and files the correct structured invoice, with VAT converted to złoty, and computes the KOD I verification link for export invoices. See the Stripe + KSeF integration and export invoices in KSeF.

Frequently asked questions

What is the minimum customer data I must collect in Stripe?

A business-vs-consumer flag (the presence of a valid tax id), the legal name, the country (the most important field), a full billing address, and the VAT/NIP number. For cross-border B2C, add two non-contradictory location evidences. Without a country and tax id the sale becomes B2C and is not filed to KSeF.

Does Stripe file to KSeF and render the reverse-charge legend?

No. Stripe collects the data and computes tax (Stripe Tax), but it does not file to KSeF, does not add the Polish reverse-charge legend, and validates only the format of a tax id, not its legal validity. KSeF Kit builds and files the FA(3) and adds the legends.

What happens if the customer does not provide a tax id?

Without a valid tax id the sale silently becomes B2C and is not filed to KSeF — which is why it is worth forcing tax-id collection right in Checkout.

How do I collect a Polish company's NIP in Stripe?

The pl_nip type is available from API version 2026-01-28.clover and stripe-ruby ≥ 18.2.0. On older versions, store Polish companies as eu_vat with a PL + 10-digit value and strip the PL prefix when you build the FA(3).

Is a VAT number from Checkout enough for reverse charge?

The number is the necessary minimum, but collecting it is not enough on its own. Reverse charge should rely on an EU VAT number confirmed in VIES. This is one of the areas where consulting an accountant is warranted.