Skip to main content

Event Overview

Event Type: VERIFICATION_NEEDED Category: Payment Verification Description: A payment needs verification details before it can settle This webhook names what a payment still owes before it can be filed. It is the general verification ask. Every payment rail sends the same seven data keys; the credit’s own details (amount, account) are in PAYMENT_SUCCESSFUL.
Not sent for LRS payments. A payment settling under an LRS purpose code receives LRS_VERIFICATION_NEEDED instead, which names documents as well as fields. It never receives both.A payment whose purpose code is not yet known still receives this one; the LRS event takes over once the code is declared.

When the webhook is sent

  1. A Virtual Bank Account credit became a payment that is missing verification details. The event follows PAYMENT_SUCCESSFUL and names what is outstanding.
  2. The verification status changed — the payment moved to ACTION_REQUIRED, IN_REVIEW or EXPIRED.
  3. A verification submit was refused on a payment with no LRS checklist. The event names what to fix — the single item that failed, not everything the payment still owes. On a B2B services payment this covers the finalizing call’s own checks: the purpose code, the invoice amount, the declaration, and the documents cited for the invoice.
  4. EximPe review sent a B2B services verification back for changes. The payment returns to ACTION_REQUIRED and you can send again. message carries the reviewer’s comment rather than the standard sentence, and action_required_fields names what the checklist still owes.
  5. A B2B services submit passed. The set was filed — through Submit Verification Details or by the merchant in the dashboard — and the payment moved to Under Review to wait for an EximPe review decision. verification_status is "IN_REVIEW" and the list is empty. It fires again on each resubmit after a send-back.
A verified payment sends no webhook — VERIFIED means nothing is outstanding, so there is nothing to act on. Do not wait on it to confirm verification.
EximPe approving or rejecting a B2B services verification raises VERIFICATION_STATUS, not this event. Only the send-back raises VERIFICATION_NEEDED. An approval leaves settlement_status at UNDER_REVIEW; a rejection moves it to NOT_APPLICABLE and raises a full refund — Get Verification Requirements reports both.
IN_REVIEW is how a B2B services payment says it is under review. PAYMENT_UNDER_REVIEW is sent for LRS payments only, so a filed B2B services set arrives here, with verification_status: "IN_REVIEW" and an empty list.
Not every refused submit raises this event. It is raised only where the refusal maps to a checklist item; a call refused for any other reason (an unreadable body, or a set that has already been filed) answers in the response and raises nothing. Treat the response as authoritative for your own calls, and this event as how you learn about changes you did not make. The webhook is delivered only if your merchant account (or parent, for sub-merchants) has a webhook URL configured. Without one, nothing is sent to you.

Delivery Details

Delivery: batched, up to about 2 minutes. See Delivery and duplicates.

Headers

Verifying. The body is serialised once and those exact bytes are both sent and signed, so hashing the raw request body as received is correct — do not re-serialise the parsed JSON first. Both signature headers are sent. Verify V2 (recommended) or V1 — see Verifying webhooks.

Payload Schema

message reads “Payment verification action required” on every one of these, including IN_REVIEW — it is not a description of the state. It is not fixed either: the sandbox ON_HOLD event says “Payment settlement is on hold”. Branch on verification_status, never on message.

Field Specifications

string
required
Always "VERIFICATION_NEEDED" for this webhook event
string
required
UTC, no timezone suffix, e.g. "2026-02-13T10:30:00.123456". Parse tolerantly — fractional seconds can be absent.
string
required
API version of your account, e.g. "3.0.0"
string
required
Unique ID of this event (a UUID, not an ordering counter). A retry resends the same value; use it to de-duplicate.Example: "550e8400-e29b-41d4-a716-446655440000"
object
required
Seven keys, always the same seven: payment_id, order_id, link_id, verification_status, message, action_required_fields, payment_verification_expiry

Reading action_required_fields

The codes come from whichever check raised the event, and there are two vocabularies. Both are answered through an API, and the codes tell you which one.

Order fields

Raised for card and collect payments, and for a credit that has not yet been classified: Supply these with Submit Payment Verification Details — with two exceptions. invoice_file is a file on the order, uploaded with POST /pg/orders/{order_id}/documents/ and document_type: INVOICE. country_of_origin is not settable through the API today; raise it with support if it is asked for.

Classification

Two facts decide which checklist a payment answers to, and either one that has not been declared appears in the same list:
business_model is listed until it is declared. Send it with purpose_code through Submit Verification Details.
Declaring the pair changes what you are asked for. Without a purpose code there is no checklist, so the event can only name the generic order fields. Declare both — through Submit Verification Details — and the payment’s real checklist takes over. If that checklist is an LRS one, the payment switches to LRS_VERIFICATION_NEEDED and stops receiving this event.

Checklist codes

Once a payment is classified and its checklist is not an LRS one, the list holds that checklist’s outstanding codes — buyer_city, buyer_state, buyer_email, iec, buyer_pan, invoice, and so on. Send these back through Submit Verification Details, under the same codes.
Declaring the classification can raise a fresh ask. If the new checklist is an LRS one, it arrives as LRS_VERIFICATION_NEEDED. If it is a B2B goods or B2B services one that still owes items, a new VERIFICATION_NEEDED names them. Any other checklist raises nothing: read its codes from Get Verification Requirements after you classify.
Do not hardcode the list. Get Verification Requirements returns the whole set for a payment, each item carrying its own satisfied flag, and it is revised as the underlying regulatory matrix is. Read it rather than reproducing it.

What to Do When You Receive This Webhook

  1. Respond with HTTP 2xx (e.g. 200 OK) as soon as you have accepted the payload, so the delivery is not retried.
  2. Verify the signature against the raw request body — prefer X-Webhook-Signature-V2.
  3. Use payment_id and order_id to reconcile with your system.
  4. Handle based on verification_status:
    • ACTION_REQUIRED — read action_required_fields, collect what it names, and send it back. If you are unsure which endpoint takes a given code, GET the payment’s verification requirements: anything it lists is answered on that same path.
    • IN_REVIEW — nothing to do. Record that the payment is under review.
    • EXPIRED — the verification window closed and the amount is refunded to the buyer. action_required_fields records what lapsed, but nothing you send reopens it. Close the payment out on your side.
  5. Watch payment_verification_expiry while the status is ACTION_REQUIRED and it is not null. It is the deadline the payment is working to, and it can move between events.
The event is not the only way to read this. Get Verification Requirements is authoritative and idempotent — call it any time an event was missed, arrived out of order, or you simply want to reconcile. It also reports settlement_status, which tells you whether sending anything is still possible.

Get Verification Requirements

The whole set, on demand, with settlement_status.

Submit Payment Verification Details

Where the order fields go.

LRS_VERIFICATION_NEEDED

The LRS payment’s version of this event.

PAYMENT_UNDER_REVIEW

Same body, empty list — nothing is owed any more.