> ## 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

# Start

> The Paymove payment gateway — how the payment flow works and what you need to integrate.

With the Paymove payment gateway, accepting online payments is simple. As a merchant you initiate the transaction via our API or SDK, and your customer pays on a secure, ready-made payment page.

As soon as the payment is completed, your system receives an automatic notification.

<Info>
  You can try a ready-made integration in the [Paymove demo shop](https://demo.checkout.paymove.io/).
</Info>

## How does a payment work?

```mermaid theme={"theme":{"light":"one-light","dark":"one-dark-pro"}}
sequenceDiagram
    participant M as Your server
    participant P as Paymove API
    participant C as Paymove Checkout
    participant K as Customer

    M->>P: Create payment (amount, orderId, returnUrl)
    P->>M: { redirectUrl }
    M->>K: Redirect to redirectUrl
    K->>C: Customer completes payment
    C->>P: Payment completed
    P->>M: Webhook + X-Paymove-Signature header
    M->>M: Verify signature
    M->>P: { "status": "ok" }
    C->>K: Customer clicks "back to shop" (optional)
```

| Step | Who         | What happens                                                                                               |
| ---- | ----------- | ---------------------------------------------------------------------------------------------------------- |
| 1    | Your server | Calls the Paymove API with amount, `externalId` and `returnUrl`                                            |
| 2    | Paymove     | Returns `redirectUrl` -  the checkout page address                                                         |
| 3    | Customer    | Is redirected to checkout and enters payment details                                                       |
| 4    | Paymove     | Sends a signed webhook to the registered URL -  by default only for the `COMPLETED` status                 |
| 5    | Your server | [Verifies the signature](/en/webhook-signature), responds with `{ "status": "ok" }` and fulfills the order |
| 6    | Customer    | Sees the confirmation screen and **may** click "back to shop", which takes them to `returnUrl`             |

<Warning>
  Fulfil the order only after a verified webhook (step 5), never after the customer returns to `returnUrl` (step 6). Step 6 requires a click and may never happen, and `returnUrl` itself can be opened without paying for the order.
</Warning>

## What you need to integrate

| Data        | Format                                                | Description                                                                                     |
| ----------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `apiKey`    | `sk_test_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` | Authorization key passed in the `X-API-KEY` header. Sandbox: `sk_test_`, production: `sk_live_` |
| `productId` | `2f6c19e8-84a7-4f50-b950-8d5a05e0bbf2`                | UUID identifying your store in the Paymove system                                               |

You can generate your `API key` and `productId` in the [Paymove Panel](https://panel.paymove.io).
