> ## 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. Registering a webhook requires both `retries` and `expectedCode` - omitting either returns HTTP 500, and `retries: 0` means no retry at all. 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. If the merchant has no `productId` yet, do not stop at a placeholder: ask for the API key, the `partnerId` and the shop name, propose defaults for `location` and `timezone` (`Europe/Warsaw`), offer the optional fields once, then create the product for them with `POST /api/product/pay` and take `productId` from `id` in the response. Do the same for the webhook: register it, then assign it to the product. Guided procedure: https://docs.paymove.io/skill.md (Steps 1-2).
> 15. 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

# Aktywacja Apple Pay

> Apple Pay w przycisku płatności: domena strony w metadata.merchantDomain produktu i plik weryfikacyjny Apple, który przygotowuje paymove.

W modalu strona płatności paymove działa w iframie osadzonym na **Twojej** stronie. Apple pozwala uruchomić arkusz Apple Pay tylko na domenie, która jest u niego zarejestrowana i zweryfikowana. Domyślnie zarejestrowane są wyłącznie domeny paymove, dlatego Apple Pay w widgecie wymaga jednorazowego onboardingu Twojej domeny.

BLIK i Google Pay działają w widgecie od razu - ta strona dotyczy wyłącznie Apple Pay.

<Steps>
  <Step title="Podaj domenę w produkcie">
    Ustaw `metadata.merchantDomain` produktu, który osadzasz w widgecie.
  </Step>

  <Step title="Napisz do nas">
    Wyślij domenę na [integration@paymove.io](mailto:integration@paymove.io). Zarejestrujemy ją w Apple i odeślemy Ci plik weryfikacyjny.
  </Step>

  <Step title="Opublikuj plik weryfikacyjny">
    Wystaw plik pod stałym adresem na swojej domenie.
  </Step>

  <Step title="Poczekaj na potwierdzenie">
    Gdy Apple zweryfikuje domenę, potwierdzimy Ci rejestrację - od tej chwili Apple Pay działa w modalu.
  </Step>
</Steps>

## 1. `merchantDomain` w produkcie

`merchantDomain` to domena strony, na której wklejasz skrypt widgetu - ta, którą klient widzi w pasku adresu. **Nie** domena paymove z adresu skryptu.

Najwygodniej podać ją od razu przy tworzeniu produktu:

```
POST /api/product/pay
```

```json theme={"theme":{"light":"one-dark-pro","dark":"one-dark-pro"}}
{
  "partnerId": "78562c79-2f5c-4415-8af4-c871eea92ef2",
  "productType": "PAY",
  "name": "Fundacja Przykład",
  "location": "Warszawa",
  "timezone": "Europe/Warsaw",
  "metadata": {
    "locale": "pl-PL",
    "merchantDomain": "fundacja.example.com"
  }
}
```

Do istniejącego produktu dodasz ją aktualizacją. Uwaga na dwie różnice względem tworzenia produktu:

```
PATCH /api/product/pay/{productId}
```

```json theme={"theme":{"light":"one-dark-pro","dark":"one-dark-pro"}}
{
  "productMetadata": {
    "locale": "pl-PL",
    "logoUrl": "https://fundacja.example.com/logo.png",
    "merchantDomain": "fundacja.example.com"
  }
}
```

<Warning>
  * W aktualizacji pole nazywa się **`productMetadata`**, a nie `metadata`. Body z `metadata` zwróci `200`, ale niczego nie zmieni - nieznane pola są ignorowane.
  * `productMetadata` **zastępuje całe metadane** produktu. Przepisz w nim wszystkie pola, które już ustawiłeś (`locale`, `logoUrl` i pozostałe) - pominięte zostaną wyczyszczone.
</Warning>

<Info>
  Jeśli nie zarządzasz produktem przez API, podaj domenę w wiadomości z kroku 2 - ustawimy `merchantDomain` po naszej stronie.
</Info>

Zasady:

* **Sama domena** - bez `https://`, portu, ścieżki i ukośnika na końcu: `fundacja.example.com`. Jeśli wyślesz pełny adres, API zostawi z niego samą domenę i zamieni ją na małe litery. Wartość, z której nie da się wyciągnąć poprawnej domeny, kończy się kodem `400`.
* **Dokładnie ta domena**, na której działa strona. `example.com` i `www.example.com` to dla Apple dwie różne domeny - podaj tę, pod którą klient faktycznie widzi stronę (i najlepiej przekierowuj drugą na nią).
* **Jedna domena na produkt.** Jeśli ten sam produkt ma działać w widgecie na kilku domenach, napisz do nas - każdą domenę trzeba zarejestrować w Apple osobno.
* `localhost` i domeny bez publicznego HTTPS nie przejdą weryfikacji Apple. Apple Pay testuj na domenie dostępnej z internetu.

## 2. Zgłoszenie domeny

Napisz na [integration@paymove.io](mailto:integration@paymove.io) i podaj:

* domenę (lub domeny), na której osadzasz widget,
* identyfikatory produktów (`productId`), które będą tam działać,
* środowisko - sandbox, produkcja albo oba.

Zarejestrujemy domenę w Apple dla identyfikatora sprzedawcy paymove i odeślemy Ci **plik weryfikacyjny** wygenerowany dla Twojej domeny.

<Info>
  Pliku nie wygenerujesz samodzielnie na swoim koncie Apple Developer - jest powiązany z identyfikatorem sprzedawcy Apple należącym do paymove. Własne konto Apple Developer nie jest potrzebne.
</Info>

## 3. Plik weryfikacyjny

Wystaw otrzymany plik dokładnie pod tym adresem:

```
https://fundacja.example.com/.well-known/apple-developer-merchantid-domain-association
```

Apple sprawdza go automatycznie, więc musi być:

* dostępny **publicznie przez HTTPS**, bez logowania, bez blokady geograficznej i bez ochrony przed botami (Cloudflare challenge, WAF),
* pod **dokładnie tą ścieżką** - katalog `.well-known` w głównym katalogu domeny, nazwa pliku **bez rozszerzenia**,
* serwowany **bez przekierowania** (kod `200`, nie `301`/`302`),
* w **niezmienionej postaci** - nie edytuj go i nie zmieniaj kodowania.

Sprawdź go przed zgłoszeniem gotowości:

```bash theme={"theme":{"light":"one-dark-pro","dark":"one-dark-pro"}}
curl -i https://fundacja.example.com/.well-known/apple-developer-merchantid-domain-association
```

Oczekiwany wynik to `HTTP/2 200` i treść pliku od pierwszego bajtu. Przykładowe konfiguracje:

<CodeGroup>
  ```nginx nginx theme={"theme":{"light":"one-dark-pro","dark":"one-dark-pro"}}
  location = /.well-known/apple-developer-merchantid-domain-association {
    alias /var/www/apple/apple-developer-merchantid-domain-association;
    default_type text/plain;
  }
  ```

  ```text Next.js / Vite / statyczny hosting theme={"theme":{"light":"one-dark-pro","dark":"one-dark-pro"}}
  public/.well-known/apple-developer-merchantid-domain-association
  ```

  ```text WordPress theme={"theme":{"light":"one-dark-pro","dark":"one-dark-pro"}}
  Wgraj plik przez FTP/SFTP do katalogu głównego instalacji:
  /.well-known/apple-developer-merchantid-domain-association
  (bez wtyczek przepisujących adresy - plik musi być serwowany wprost)
  ```
</CodeGroup>

<Warning>
  Nie usuwaj pliku po weryfikacji. Apple może sprawdzić domenę ponownie, a brak pliku wyłączy Apple Pay w widgecie.
</Warning>

## 4. Potwierdzenie i test

Gdy plik jest na miejscu, daj nam znać - poprosimy Apple o weryfikację i potwierdzimy wynik. Potem przetestuj płatność:

* w **Safari na iPhonie, iPadzie albo Macu** z kartą dodaną do Apple Wallet - w innych przeglądarkach Apple Pay się nie pokazuje,
* na stronie **pod zgłoszoną domeną** - wersja testowa pod inną domeną (np. `staging.example.com`) wymaga osobnej rejestracji.

## Co się dzieje bez rejestracji

Dopóki domena nie jest zarejestrowana, Apple odrzuca sesję płatniczą: klient wybiera Apple Pay, ale arkusz płatności się nie otwiera albo zamyka się z błędem. Pozostałe metody działają normalnie. Jeśli nie planujesz rejestracji, wyłącz Apple Pay dla produktu osadzanego w widgecie - napisz do nas, a zrobimy to za Ciebie.

Rejestracja nie jest potrzebna, gdy klient płaci **poza widgetem** - na stronie płatności otwartej z linku albo z kodu QR arkusz Apple Pay pokazuje się na domenie paymove.

<Info>
  Ta sama procedura dotyczy [widgetu checkoutu](/sdk/widget#apple-pay-w-modalu). Jeśli osadzasz na jednej domenie oba widgety, zgłoś to w jednej wiadomości - podaj wszystkie produkty, które mają tam działać.
</Info>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.