> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paymove.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> ## paymove integration rules for AI agents
>
> These rules are verified against the live API. Follow them exactly.
>
> 1. Amounts are INTEGERS in grosze (minor units). `1000` means 10.00 PLN. PLN is the only supported currency and there is no currency field in the API.
> 2. A float `price` (e.g. `12.99`) is SILENTLY TRUNCATED to 12 grosze and still returns HTTP 200. Always send an integer: `Math.round(pln * 100)`.
> 3. Authenticate with the `X-API-KEY` header. Never `Authorization: Bearer`. Sandbox keys start with `sk_test_`, production keys with `sk_live_`.
> 4. Server-side only. A call from a merchant page is rejected. Never put the key in frontend code.
> 5. Unknown request fields are silently ignored and still return HTTP 200 — a wrong body shape looks like success. Match the documented shape exactly.
> 6. A missing `externalId` returns HTTP 500 `Something went wrong`, not 400. A missing `price` or `details.returnUrl` returns HTTP 200 and a usable `redirectUrl` — no error at all. Validate the body yourself before sending it.
> 7. Always verify the `X-Paymove-Signature` header on incoming webhooks before trusting them: https://docs.paymove.io/en/webhook-signature.md
> 8. Errors are `{"status": <int>, "message": "<text>"}`. Branch on the HTTP status only — never on `message`, which is unstable and leaks internal class names.
> 9. There is no rate limiting, no HTTP 429, no HTTP 422, no `Idempotency-Key` header and no API versioning. Do not write code that handles them.
> 10. Re-POSTing an `externalId` that already exists returns HTTP 200 with the ORIGINAL `redirectUrl` and silently discards EVERY field you send — the new price, description and details are all ignored. Use `PATCH /api/pay/product/{productId}/subproduct/{externalId}` to change a price.
> 11. Webhooks fire only on `COMPLETED` by default, and `retries` defaults to `0` (no retries) unless you set it explicitly. Delivery counts as successful when the HTTP status equals `expectedCode` — the response body is never inspected.
> 12. Never fulfil an order on the `returnUrl` redirect. The checkout does not redirect there by itself: the customer has to click "back to shop", and inside the widget modal that redirect never happens. Fulfil only in the webhook handler, after verifying the signature.
> 13. Do not pin a version of `@paymove-io/sdk` — install the latest.
> 14. Full documentation index: https://docs.paymove.io/llms.txt · Copy-paste quickstart: https://docs.paymove.io/en/quickstart.md · Agent skill: https://docs.paymove.io/skill.md

# Integracja

> Podstawowa integracja z linkami płatności: utwórz produkt, dodaj subprodukt i odbierz link do płatności za cokolwiek.

Podstawowy scenariusz integracji składa się z dwóch kroków. **Produkt tworzysz jednorazowo**, a następnie dla każdej płatności - niezależnie od tego, czego dotyczy - tworzysz **subprodukt**. W odpowiedzi otrzymujesz kod QR z linkiem przekierowującym płacącego do strony płatności.

Wszystkie żądania autoryzujesz kluczem API przekazywanym w nagłówku `X-API-KEY`.

<Info>
  Przykłady używają środowiska sandbox: `https://gateway-api.sandbox.paymove.io`.
</Info>

## Krok 1: Utworzenie produktu

Produkt reprezentuje Twoją działalność w systemie Paymove i jest kontenerem dla subproduktów (pojedynczych płatności). Tworzysz go **tylko raz**, przy starcie integracji.

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
curl --request POST \
  --url https://gateway-api.sandbox.paymove.io/api/product/pay \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  --data '{
    "partnerId": "78562c79-2f5c-4415-8af4-c871eea92ef2",
    "productType": "PAY",
    "name": "Płatności Online",
    "shortName": "PAYLINK",
    "location": "Warszawa",
    "timezone": "Europe/Warsaw"
  }'
```

| Pole          | Wymagane | Opis                                             |
| ------------- | -------- | ------------------------------------------------ |
| `partnerId`   | Tak      | Identyfikator partnera (nadawany przez Paymove). |
| `productType` | Tak      | Typ produktu - zawsze `PAY`.                     |
| `name`        | Tak      | Nazwa produktu.                                  |
| `shortName`   | Tak      | Krótka nazwa wyświetlana.                        |
| `location`    | Tak      | Lokalizacja (np. miasto).                        |
| `timezone`    | Tak      | Strefa czasowa IANA (np. `Europe/Warsaw`).       |

**Odpowiedź (200):**

```json theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
{
  "id": "d0a834f9-94a4-4b3a-aa10-27d911e3633f",
  "name": "Płatności Online",
  "location": "Warszawa",
  "partner": {
    "id": "78562c79-2f5c-4415-8af4-c871eea92ef2",
    "name": "Nazwa Partnera Sp. z o.o.",
    "productTypes": ["PAY"]
  },
  "timezone": "Europe/Warsaw",
  "shortName": "PAYLINK",
  "emailEnabled": true,
  "smsEnabled": false,
  "fee": {
    "id": "01f9754e-78e3-4b2c-8186-d6862598a95a",
    "minimum": 30,
    "amount": 5,
    "fixed": false
  },
  "productType": "PAY",
  "status": "ACTIVE",
  "creator": "PAYMOVE",
  "reviewEnabled": false,
  "createdAt": 1783245692.623763835,
  "updatedAt": 1783245692.623763835
}
```

Pole `id` z odpowiedzi to identyfikator produktu (`productId`), którego użyjesz w kroku 2.

## Krok 2: Utworzenie subproduktu (link płatności)

Subprodukt reprezentuje **pojedynczą płatność za cokolwiek** - konsultację, rezerwację, składkę, naprawę, zamówienie telefoniczne. W URL podmień identyfikator produktu (`productId`) otrzymany w kroku 1.

W polu `details` przekazujesz dowolne pary klucz-wartość opisujące, czego dotyczy płatność - to one zostaną wyświetlone płacącemu na stronie płatności.

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
curl --request POST \
  --url https://gateway-api.sandbox.paymove.io/api/pay/product/d0a834f9-94a4-4b3a-aa10-27d911e3633f/subproduct \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  --data '{
    "externalId": "payment-2026-0001",
    "imageFormat": "png",
    "bannerType": "ticket",
    "price": 15000,
    "details": {
      "Tytuł płatności": "Konsultacja online - 60 minut",
      "Za co": "Usługa doradcza",
      "Odbiorca": "Twoja Firma Sp. z o.o.",
      "Nr płatności": "payment-2026-0001"
    }
  }'
```

| Pole          | Wymagane | Opis                                                                                        |
| ------------- | -------- | ------------------------------------------------------------------------------------------- |
| `externalId`  | Tak      | Identyfikator płatności w Twoim systemie. Wyświetlany w panelu Paymove.                     |
| `imageFormat` | Tak      | Format grafiki kodu QR: `svg` lub `png`.                                                    |
| `bannerType`  | Tak      | Typ banera/karty (np. `ticket`) - wpływa na prezentację.                                    |
| `price`       | Tak      | Kwota w groszach (np. `15000` = 150,00 PLN).                                                |
| `details`     | Nie      | Dowolne pary klucz-wartość opisujące płatność - wyświetlane płacącemu na stronie płatności. |

<Info>
  Wartości z `details` są wyświetlane płacącemu na stronie płatności - klucz to etykieta, a wartość to prezentowany tekst. Płatność może dotyczyć czegokolwiek: opisz ją tak, żeby płacący wiedział, za co płaci (np. „Tytuł płatności", „Za co", „Odbiorca").
</Info>

## Odpowiedź: kod QR z linkiem płatności

Odpowiedź (200) to **binarna zawartość obrazka** z kodem QR w formacie wskazanym w `imageFormat` (SVG lub PNG), zwracana z nagłówkiem `Content-Type: application/octet-stream`. To nie jest JSON - zapisz body odpowiedzi bezpośrednio do pliku, np.:

```bash theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
curl --request POST \
  --url https://gateway-api.sandbox.paymove.io/api/pay/product/{productId}/subproduct \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' \
  --data '{ ... }' \
  --output link-platnosci.png
```

Grafika zawiera gotowy do użycia baner z kodem QR przekierowującym do płatności (dla `png` np. 300x780 px). Możesz go wysłać e-mailem lub SMS-em, umieścić na wydruku albo wyświetlić na ekranie - płacący po zeskanowaniu (lub kliknięciu linku) trafia bezpośrednio do opłacenia należności.

## Co dalej?

<CardGroup cols={2}>
  <Card title="DocPay: webhooki" icon="webhook" href="/products/docpay/tutorial-webhook">
    Dodaj webhook i otrzymuj automatyczne powiadomienia o każdej zakończonej płatności.
  </Card>

  <Card title="REST API" icon="code" href="/products/docpay/rest-api">
    Pełna dokumentacja endpointów PAY API: cennik, formularze, personalizacja UI i webhooki.
  </Card>
</CardGroup>
