Skip to content

Changelog

Download .md

Changes are announced here. Within v1 they never require you to change working code — see Versioning & deprecation.

New

  • Fulfil an order, a guide that takes an order from session creation to a verified webhook, in Node.js, PHP and Python.
  • Refund object. POST /gateway/sessions/{id}/refund/ now returns the refund: a re_… id, a status of PENDING, SUCCEEDED or FAILED, and a processor_message. It replaces the earlier response fields (refund_id, refunded_amount, automated_refund, epg_error).
  • Idempotency-Key on refunds, so a timed-out refund can be retried without refunding twice. See Retrying safely.
  • Refund events refund.succeeded and refund.failed, for refunds issued through any channel, and a refunds list on every session.
  • session.attempt_failed, sent for every declined payment attempt.
  • locale on sessions chooses the payment page’s language: fr, en, or auto (the default) to follow the buyer’s browser. The card-entry page now opens in the same language as the payment page. See Language.
  • The API reference now documents every webhook event and every error response. The OpenAPI specification can be downloaded at /openapi/merchant-api.yaml.
  • Markdown version of every guide, at the page’s address with .md in place of the trailing slash (for example /guides/webhooks.md), so a single page can be handed to an AI assistant. /llms.txt now links to these.
  • Send a test event in your dashboard now covers every event, including session.attempt_failed and the refund events.

Changed

  • The payment page can no longer be shown in an iframe. See Websites and mobile apps.
  • A session created without locale follows the buyer’s browser; the payment page used to open in French.
  • A webhook’s body id is now the same value as its X-Paymee-Webhook-Id header.
  • Webhook retries now span about 3 days (up to 10 deliveries) instead of about a day.
  • Webhooks are sent within seconds after the change they describe, independently of the buyer’s checkout; events can arrive out of order.
  • Requests refused by a business rule now always answer 422 (some refund refusals answered 400).
  • Validation errors carry specific codes such as required, blank and max_length instead of invalid for every case.
  • Optional text fields sent as "" count as not given, and metadata accepts numbers and booleans (stored as text).
  • webhook_url is no longer looked up in DNS when you create a session; the address is checked when each event is delivered.
  • An unexpected server error now answers an internal-error problem document.
  • Every amount — in responses and in webhooks — now has exactly the currency’s decimals ("10.500"). Some response fields (a fetched session’s amount, an attempt’s fee_amount and net_amount, and the webhook payment amounts) used to show five ("10.50000"); a missing net_amount is null.
  • Every timestamp now ends in Z; some webhook timestamps used +00:00.
  • The same data has the same name in API responses and webhooks: the buyer is a nested buyer object (replacing the buyer_first_name, buyer_last_name, buyer_email and buyer_phone fields of API responses); the time a session ended is completed_at (replacing paid_at in webhooks); an attempt’s number is attempt_number; and an attempt’s failure_code is the acquirer’s decline code everywhere (it was always declined in API responses), with its reason in failure_message.
  • checkout.session.expired no longer repeats the session id as payment_session_id: use data.id.