Skip to main content
This page walks through a complete payment gateway integration: creating a payment, redirecting the customer and safely handling the payment notification. The code is framework-agnostic - examples in curl and Node.js.

What you need

Creating a product and registering a webhook are one-time steps. If you have not done them yet, start with Configuration and come back here.
Make every call server-side. The API key must not reach frontend code, and a browser request is rejected by CORS.

1. Create a payment

Response:
In Node.js:
price must be an integer in grosze. The value 12.99 is silently truncated to 12 grosze and the API still returns 200. Hence Math.round(amount * 100) in the example.
Store the externalId parameter from the returned redirectUrl (here ec6RtwTZKb). It is a payment hash generated by Paymove - different from your own externalId - and it is what you use to check the status later.
Working in Node.js or TypeScript? Instead of hand-written fetch, use the official SDK - npm install @paymove-io/sdk. It is MIT-licensed, has zero dependencies, requires Node 18+ and ships TypeScript types. It assembles the nested request body for you and returns typed errors. Details: JavaScript SDK.The SDK does not include webhook signature verification - you write step 3 yourself either way.

2. Redirect the customer

The customer lands on the Paymove checkout, picks a payment method and completes the transaction. Afterwards they see a confirmation screen with a “back to shop” button - only a click on it takes them to the address given in details.returnUrl.
Returning to returnUrl does not mean the payment succeeded - and it may never happen. A customer who closes the tab never gets there, and the address can be opened directly, without paying. Show only a “processing your payment” message on that page - fulfil the order after the webhook.

3. Receive and verify the webhook

This is the only trustworthy confirmation of payment. The handler below does four things: takes the raw body, verifies the signature, responds immediately and fulfils the order idempotently.
Your server must respond with a status equal to expectedCode (200 by default) - the response body is not inspected.
Fulfil orders idempotently, keyed on externalId. Paymove may redeliver the same notification, and a double fulfilment means shipping the goods twice.
By default the webhook arrives only for the COMPLETED status. If you also need notifications about cancellations and failures, write to integration@paymove.io. Full description: Payment statuses.

4. Fallback status check

If the customer returned to returnUrl but the webhook has not arrived yet, you can poll for the status. Use the payment hash you stored in step 1:
Note the host: this query is served by a different host (pay-api.sandbox.paymove.io, in production pay-api.paymove.io) than payment creation. Through gateway-api the path is not routed at all and returns 404 with the text No route found for: GET …. The endpoint needs no API key.
Treat this as a supplement, not a replacement for the webhook - the webhook is the source of truth.

Before going live

  • Switch the base URL to https://api.paymove.io and the key to sk_live_….
  • Make sure externalId is unique per order - reusing it returns the old payment with the old amount.
  • Make sure the amount passed to price is computed server-side, not sent from the browser.
  • Set retries when registering the webhook - it defaults to 0, meaning no retries.

What’s next

REST API

Every parameter, full responses and changing a payment’s amount.

Signature verification

Code for Node.js, Python and Java plus a test vector.

Error codes

What each error means and how to handle it.

JavaScript SDK

A ready-made client for Node.js.