Changelog
Changes arrive with dates and migration context.
Every public contract change is recorded here. A generally available endpoint or field receives at least 12 months' notice before removal; each deprecation entry must name its replacement and earliest removal date.
12-month minimum deprecation window
No GA removal is currently scheduled. Preview surfaces may change before GA and are identified as such in their contract.
- API 2026-07-15 · additive
Safety classes say what a call does
x-perion-safety.class gains three values split out of configuration: credentials (POST /oauth/token gets a token), records (customers, contact requests and test clocks are created or changed) and redelivery (event and endpoint replays send an event again). configuration now covers settings only, such as webhook endpoints, plans and the collection policy. Nothing else in x-perion-safety changes, and no operation's agent value changes. Treat a class you don't recognize as configuration. Eight operation summaries now read plainly, for example GET /v1/payment_intents/{id} is "Retrieve a payment".
- API 2026-07-15 · additive
A refused token says to get a new one first
Problem guidance gains the retry value after_new_token: get a new access token from POST /oauth/token, then repeat the identical request with the same Idempotency-Key and body. invalid_token (401) now carries it instead of same_request, so an agent that acts on retry no longer repeats a request that will be refused again. same_request keeps its meaning. The do_not vocabulary gains bypass_merchant_decision ("Don't use another key or route to get around the merchant's decision"), which api_client_paused and api_client_policy_operation_not_allowed now carry in place of work_around_limit. Three problem titles read plainly: attempt_in_flight is "Payment already sent to the customer", payment_link_in_flight "Payment from this link is still confirming" and intent_not_confirmable "Payment can't join this checkout". Every change is additive. Treat a retry value you don't recognize as never, and stop.
- PerionPayments.js 1.0.7
A payment form that didn't load says no payment was started from it
When the drop-in's secure frame never becomes ready, PerionPayments.js 1.0.7 tells the payer the payment form didn't load, that no payment was started from it, and that a payment they approved earlier isn't affected. It offers one action: Try again, which reconnects the same checkout session, or Reload page when the frame speaks a protocol this version doesn't. A frame that was sent the client secret but never became ready is stopped, so nothing can start from it later, and the panel no longer repeats the PerionPayments name inside your page. Events, error codes and frame protocol 1 are unchanged. Version 1.0.6 and every earlier exact-version channel stay published unchanged; to upgrade, change the script's src and integrity together.
- API 2026-07-15 · additive
Exports filter by the API client that created a row and by the customer's PER- reference
POST /v1/export_jobs accepts filters.api_client (cl_) on payments and refunds exports and filters.payer_reference on payments exports, matching api_client= and payer_reference= on their lists. payer_reference takes the reference in any form a person says it and the job records it as PER-XXXX-XXXX. An api_client that is not one of your clients in this environment is refused with 400 invalid_export instead of producing an empty file; paused and revoked clients are accepted, so their history stays exportable. payments_v1 files gain payer_reference, created_by_id and created_by_name on the right, and refunds_v1 files gain created_by_id and created_by_name; the creator columns are blank when a person, the checkout or PerionPayments made the row. Existing columns keep their names and positions.
- API 2026-07-15 · additive
A paid payment link is a notification
When a payment through one of your payment links succeeds, GET /v1/notifications gains one notice for it in the payment's environment: category money, action_required false, a title such as "Paid · ZiG 81.00 · Paid design consultation" (the amount and the link's description), a body naming who paid and whether the link takes more payments, and action_path /payments/{payment_intent}. There is one notice per payment, however often its event is processed; a payment that did not come through a link has none. Team members can also choose to be emailed it, in dashboard Settings > Notifications. The notification shape is unchanged; this is additive.
- API 2026-07-15 · additive
An API client's day counts its payment links and refunds, and a refusal notice names its key
GET /v1/api_client usage_today adds links_created (payment links the client created today) and refunds_created (refunds it sent today that have not failed, the ones its per-day refund limit counts), beside payments_created and refunded_minor. A merchant notification about a burst of refusals carries api_client, the client it is about, and its action_path is that client's page. Both are additive.
- API 2026-07-15 · additive
Paying for someone: discoverable payment links, verified merchants and a declared assistant
The /c/ share page and the /p/ page now link each payment link's public JSON as a JSON alternate and describe it as a schema.org Invoice in a JSON-LD data block, so a payer's assistant reads the merchant and amount from PerionPayments instead of from the page. The public merchant gains verified, verified_name, website and support_contact: when verified is true, PerionPayments vouches for the name, website and contact. Public payment methods say payer_presence: approve_on_own_phone, enter_card_on_hosted_page or complete_on_hosted_page. An assistant confirming a public checkout may name itself with the optional Perion-Payer-Agent header (<name>, or <name>; url=<https URL>), which the merchant's timeline shows as "Started by the customer's assistant"; it grants nothing, and a malformed header is refused with 400 invalid_request. The person still approves on their own phone or types their own card on the hosted payment page. See the Pay for someone guide.
- API 2026-07-15 · additive
Answers an agent can repeat: payer references, the order guard, problem guidance, previews and forward events
Payment intents carry the payer's payer_reference (PER-XXXX-XXXX), and payer_reference= on GET /v1/payment_intents finds a payment in any form a person says it: case, spaces, dashes and the PER prefix don't matter, and 0, 1 and 8 read as O, I and B. order_reference on payment intents and checkout sessions is the order guard: while one payment for the order is unresolved another is refused with 409 order_payment_unresolved, and once one has succeeded with 409 order_already_paid, both carrying the payment in existing; a declined order can be paid again under the same reference, and merchant_reference keeps its one-payment meaning. Payment links take a merchant_reference that every payment through the link carries as payment_link_reference; payments filter by order_reference= and payment_link=, and links by merchant_reference=. Payment intents and checkout sessions carry answer: paid, safe_to_fulfill, sentence, do_not and check_again_after. Every problem carries retryable, retry, who_acts, next_step and do_not, merchant_reference_reused and the order refusals carry existing, each type URL opens the code's page under /problems/, and /problems.json lists every public code. Perion-Preview: true on POST /v1/payment_intents, /v1/checkout_sessions, /v1/payment_links, /v1/refunds and /v1/subscriptions answers 200 with a preview and creates, reserves and sends nothing; a preview needs no Idempotency-Key. GET /v1/events reads forward with order=asc and after_event, holding back the newest five seconds, and takes ending_before in the default order. See the AI agents guide.
- API 2026-07-15 · additive
Agent keys are mandates: refund limits, a kill switch, attribution and a self-read
An Agent key now holds only the agent scope catalog (anything else is refused with api_client_agent_scope_not_allowed), must expire within 90 days, and must carry a per-payment limit and an operation allowlist; every write its scopes reach is a governed operation, now including payment_links:deactivate and checkout_sessions:revoke_saved_cards. An Agent key allowed refunds carries per-refund and per-day refund limits and by default refunds only payments it created; a refusal is api_client_policy_refund_limit_exceeded (422) with limit and remaining_today. An Agent key has one approval prompt waiting on a payer at most and reaches 20 different payers an hour unless its policy says otherwise (api_client_policy_prompt_reach_exceeded, 429 with Retry-After), and never receives collect_otp: a method that would ask the customer for a one-time code is refused with 409 payment_method_requires_hosted_checkout. A merchant can pause and resume any API client; a paused client is refused with api_client_paused (403) and gets no token. GET /v1/api_client returns the client's own terms, limits, authority in plain verbs, rate and today's usage, and the token response carries client_expires_at. Payment intents, payment links and refunds carry created_by, and their lists accept api_client=cl_. Every operation carries an x-perion-safety object; x-perion-moves-money and x-perion-payer-approval remain as aliases. New events: api_client.paused, api_client.resumed and api_client.expiring (seven days and one day before a key stops working). Server keys issued without terms behave as before.
- API 2026-07-15 · additive
Hosted card payments: confirm from your server, and cancel when the payer leaves
A payment limited to a card method (Visa & Mastercard or ZimSwitch) can be confirmed from your server: POST /v1/payment_intents/{id}/confirm with that method's type and rail returns requires_action with next_action.type redirect_to_url, and you send the payer's browser to next_action.url, the PerionPayments-hosted card page. Canceling a payment whose payer is on that page now answers 202 with the payment as it stands, instead of 409 attempt_in_flight: PerionPayments asks the card acquirer at once, and if nothing was submitted the payment ends failed with failure_code customer_cancelled within seconds (payment_intent.failed); if the payer paid after all, it succeeds as usual. A cancel before anything was sent still answers 200, and a cancel while a wallet prompt is out still answers 409 attempt_in_flight. Card methods are offered to internal pilot merchants only.
- PerionPayments.js 1.0.6
A card the payer already chose opens without a second choice
When the payer chooses a card method in the drop-in, or the checkout is limited to one, the frame asks PerionPayments.js to move the merchant page to the PerionPayments-hosted card page, and 1.0.6 does so only for that page on the checkout's own origin. No drop-in event fires before the page moves, so keep the order on your server: the payer comes back to return_url, or to cancel_url after leaving without paying. Frame protocol 1 is unchanged; earlier versions ignore the request and keep the frame's Continue button. Earlier exact-version SDK channels remain available.
- API 2026-07-15 · additive
Credential terms, payer prompt limits and agent-readable operations
A merchant can issue an API client as an agent credential with an expiry and a policy: a per-payment limit for each currency and the money-path operations it may perform. An expired client is refused at the token endpoint with invalid_client and code api_client_expired, and its tokens with the api_client_expired problem; policy refusals are api_client_policy_amount_exceeded (422) and api_client_policy_operation_not_allowed (403), returned before anything is created or charged. A live approve-on-device payment is refused with payer_prompt_limit_reached (429, with Retry-After) once one merchant has the allowed number of prompts waiting on one payer or has sent the hourly allowance. Money-path operations now carry descriptions, examples, x-perion-moves-money and x-perion-payer-approval. Clients issued without terms behave as before.
- PerionPayments.js 1.0.5
Wider merchant layouts
Set --perion-dropin-max-width on your mount, for example to 100%, to let the drop-in grow beyond its default 480px maximum. The frame keeps its 320px minimum usable width and reports its content height. Origin binding, payment authority and frame protocol 1 are unchanged, and earlier exact-version SDK channels remain available.
- API 2026-07-15 · additive
Optional public merchant website on receipts
Receipts may include merchant.public_website_url, an explicitly published HTTPS homepage from branding in the payment's environment. The link contains no private checkout return path, order query or payment authority. Merchants publish or remove it through an exact reviewed branding save; older clients preserve it. Receipt navigation sends no receipt referrer.
- API 2026-07-15 · additive
Public refund references on verified receipts
Refund evidence rows may include a stable public reference. The reference identifies a refund for support; it does not grant independent read access or command authority. Receipt views use it only within the original receipt capability. Started refunds remain distinct from provider-file or bank-confirmed refunds.
- API 2026-07-15 · additive
Checkout-wide card attempt budget
Checkout responses expose card_retry_budget and the latest attempt status. Three failed card attempts exhaust the allowance for that checkout; reloading, changing methods and using a continuation code do not reset it. A further card confirmation returns card_attempt_limit_reached before dispatch. Existing idempotent results remain replayable, and eligible non-card methods remain available. A failed card attempt can leave its payment intent open for another method.
- PerionPayments.js 1.0.4
Clear recovery for the original checkout
Connection failures now explain that the payment result is unknown and offer recovery for the original checkout. The recovery panel replaces the failed frame, fits narrow mounts and preserves keyboard focus on merchant fields. Exact-session reconnection, credential boundaries and frame protocol 1 remain unchanged. Existing versioned SDK artifacts remain available.
- API 2026-07-15 · additive
Stored cards on the merchant API
Cards payers save with a merchant appear as payment_method_credential objects: scheme, last four, expiry, and stored-credential eligibility, never the number. Merchants list them per customer and detach one; a detached card can no longer be named on a confirm or charged by a scheduled collection. In Sandbox, cards run through the real field frames and bank-verification ceremony against a published deterministic test-card canon.
- PerionPayments.js 1.0.3
Bounded embedded-frame readiness
A frame that opens its private message channel but does not become ready now reaches the same bounded, payer-safe recovery state as a frame that never answers. The transferred port is closed, late events are ignored, and the same checkout session can be remounted without creating another payment.
- API 2026-07-15 · additive
Public documentation boundary
The developer portal now contains curated integration guidance and the public OpenAPI contract. Complete repository documents and full-text source mirrors are not part of the public documentation surface.
- API 2026-07-15 · additive
Recurring billing lifecycle completed
Plans, consent-bound enrollment, subscription controls, invoices, test clocks, payer access, and lifecycle notifications are available through the documented public interfaces.
- Runtime hardening
Rate governance and provider capacity
Authenticated API clients receive enforced sandbox and live token-bucket limits with RateLimit headers. Provider-account capacity remains a separate upstream safety boundary.
- API 2026-07-15 · first release
Public v1 contract
Published the first versioned payment-intent, checkout, refund, event, settlement, reconciliation, export, receipt, and status contract for the deterministic sandbox.