> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eximpe.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Submit Payment Verification Details

> Send a payment’s verification details — buyer, invoice and goods fields — in a single JSON call.

## Overview

When a payment needs verification details before it can settle, this is where you send them. One call carries every field the payment is waiting on, and you can send them as you collect them rather than all at once.

Use it when you receive a [`VERIFICATION_NEEDED`](/api-reference/v3/webhooks/verification-needed) webhook with `verification_status` of `ACTION_REQUIRED`.

<Note>
  **This replaces `POST /pg/payments/{uid}/upload-verification-details/`**, which is deprecated. The old endpoint took one fixed set of fields, rewrote them all on every call, and worked on a single gateway. Move existing integrations across when convenient; build new ones here.
</Note>

## When this applies

Credits that land in a Virtual Bank Account create a payment against an order. If that order is missing anything the payment needs before it can settle, the platform emits `VERIFICATION_NEEDED` naming exactly which fields are absent. This endpoint is how you supply them programmatically, rather than editing the order in the dashboard.

<Steps>
  <Step title="Payment recorded">
    A credit is received and a payment is created against the order.
  </Step>

  <Step title="Missing fields reported">
    [`VERIFICATION_NEEDED`](/api-reference/v3/webhooks/verification-needed) fires with an `action_required_fields` array naming each one.
  </Step>

  <Step title="Supply the details">
    `POST` them to this endpoint, under the same codes the event used.
  </Step>

  <Step title="Read what is left">
    The response carries `outstanding` — the codes still owed after that call.
  </Step>
</Steps>

## A worked example

Your answers go in `fields`, keyed by code; files you have already uploaded go in `documents` as `{ "code": …, "ref": … }`.

```json theme={null}
{
  "fields": {
    "buyer_name": "Acme Imports Pvt Ltd",
    "product_description": "Cotton knitted t-shirts",
    "invoice_number": "INV-2026-0041",
    "buyer_postal_code": "560001",
    "hs_code": "6109"
  }
}
```

<Note>
  **JSON only.** Files are never posted here. Upload a file with `POST /pg/payments/{payment_id}/documents/`, which returns a `ref`, then name that `ref` under its code in `documents`.
</Note>

## Which codes to send

**The codes come from the payment, not from a fixed list.** Read them off `action_required_fields` on the webhook, or call `GET /pg/payments/{payment_id}/verification/` at any time for the full set with a `satisfied` flag on each item. What a payment is asked for depends on what it is, and it changes as the underlying regulatory requirements do — read the codes rather than hardcoding them, and a revision reaches you without a release on your side.

These are the ones an import payment is most often asked for:

| Code                                               |                                                                                                                                                                                         |
| -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `buyer_name`                                       | Name of the buyer / importer                                                                                                                                                            |
| `product_description`                              | Description of the goods or services                                                                                                                                                    |
| `invoice_number`                                   | Invoice or order number                                                                                                                                                                 |
| `invoice_date`                                     | Invoice date, `YYYY-MM-DD`                                                                                                                                                              |
| `buyer_address_line_1`                             | Street address of the buyer                                                                                                                                                             |
| `buyer_city` · `buyer_state` · `buyer_postal_code` | Rest of the buyer's address                                                                                                                                                             |
| `buyer_email` · `buyer_phone`                      | Buyer contact details                                                                                                                                                                   |
| `hs_code`                                          | Harmonised System code — asked for when the order ships physical goods                                                                                                                  |
| `iec`                                              | Importer-Exporter Code of the buying business                                                                                                                                           |
| `business_model`                                   | `B2B` or `B2C`                                                                                                                                                                          |
| `purpose_code`                                     | The FEMA/FETERS code this order settles under, e.g. `S0101`. It must be one your merchant account is enabled for — an unrecognised or un-enabled code is a `400`, never a stored value. |

Document codes work the same way; an import payment is typically asked for `invoice`.

<Note>
  **`type_of_goods` is not sent here.** It is part of the order's product details, declared when you create the order, and it is never listed as outstanding.
</Note>

<Warning>
  **`business_model` and `purpose_code` must travel together, and only once.** They place the payment, and until both are set nothing else about it can be checked — so send them first, or in the same call as the rest. Send one without the other and the call is refused naming the one you left out; once set, sending either again is a `400`.

  `business_model` is listed when nothing has *declared* it, not when it is empty — it defaults to `B2C`, so sending `"business_model": "B2C"` is a real answer rather than a no-op. Many orders arrive already classified, so `GET` the payment first if you are unsure.
</Warning>

## Send as much or as little as you have

Send three fields today and two tomorrow and you have sent five. Nothing you sent earlier is wiped by a later call, and a field's newest value wins. Nobody collects an invoice, an address and an IEC in the same instant.

<Note>
  **`finalize` defaults to `true`.** It applies only to a **complete** set and never forces an incomplete one through, so a partial send is accepted either way — you do not have to set it. Pass `finalize: false` when you have sent everything but do not want the payment's verification completed yet, and the details are recorded without it.
</Note>

<Warning>
  **That tolerance ends once verification has been filed.** A payment that has moved past `ACTION_REQUIRED` refuses further sends — `GET` the payment and read `settlement_status` before you send.
</Warning>

## The response

```json theme={null}
{
  "success": true,
  "message": "Verification details received",
  "data": {
    "payment_id": "PR7712349900",
    "status": "incomplete",
    "outstanding": ["invoice_number", "hs_code"]
  }
}
```

| Key           |                                                                                                                        |
| ------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `payment_id`  | The payment these details were recorded against.                                                                       |
| `status`      | `incomplete` — something is still owed, and `outstanding` names it. `complete` — nothing is outstanding.               |
| `outstanding` | The codes still owed **after** this write. Empty when nothing is. You do not need a second call to learn what is left. |

<Note>
  Payments that go through an additional verification step can return two further values, `in_review` and `action_required`. They do not arise on this flow.
</Note>

## Errors

A refused send answers in the standard error envelope, with `details` keyed by the offending code — so one call reports every problem at once:

```json theme={null}
{
  "success": false,
  "error": {
    "code": 40359,
    "message": "Invalid LRS request.",
    "details": {
      "buyer_citty": "Not a requirement of this payment's checklist.",
      "invoice": "This is a document code; send it under 'documents'."
    }
  }
}
```

| Message                                                | Cause                                                                         |
| ------------------------------------------------------ | ----------------------------------------------------------------------------- |
| `Not a requirement of this payment's checklist.`       | The code is not one this payment asks for.                                    |
| `This is a document code; send it under 'documents'.`  | A document code appeared as a key in `fields`.                                |
| `This is a field code; send it under 'fields'.`        | The reverse.                                                                  |
| `Blank value; omit the key instead.`                   | `null`, `""`, or whitespace. Omit the key rather than sending an empty value. |
| `Sent more than once in this call.`                    | The same document code twice in one `documents` array.                        |
| `Unknown document ref.`                                | The `ref` is not one of your uploads.                                         |
| `Already set on the order; it cannot be changed here.` | `business_model` or `purpose_code` after classification has landed.           |

<Warning>
  **An unknown key is a `400`, not a silent drop.** A misspelled `invoice_number` that we quietly ignored would leave the payment waiting forever for a field you believe you sent. Every key is checked before any is written, so one typo cannot half-apply a call.
</Warning>


## OpenAPI

````yaml POST /pg/payments/{payment_id}/verification/
openapi: 3.0.0
info:
  title: Eximpe Payment Gateway API
  description: >-
    API for payment processing and order management through Eximpe payment
    gateway. This specification is for v3 API version.
  license:
    name: Proprietary
  version: 3.0.0
servers:
  - url: https://api-pacb-uat.eximpe.com
    description: Payment Gateway Sandbox URL
security:
  - clientAuth: []
    clientSecretAuth: []
    apiVersionHeader: []
tags:
  - name: Card Tokens
  - name: Merchants
  - name: Orders
  - name: Payment Links
  - name: Payments
  - name: Refunds
  - name: Settlements
  - name: Subscriptions
  - name: Virtual Bank Accounts
    description: Create and manage virtual bank accounts and read collected payments.
paths:
  /pg/payments/{payment_id}/verification/:
    post:
      tags:
        - LRS
      summary: Submit verification details
      description: >-
        Sends verification details for a payment, keyed by the same codes the
        verification webhook and `GET /pg/payments/{payment_id}/verification/`
        use. There is nothing to map: every one of those places names an item
        under `code`.


        **JSON only.** `fields` is an object; `documents` is a list of `{code,
        ref}` naming files uploaded earlier through [Upload
        Document](/api-reference/v3/lrs/upload-document). Files are never posted
        to this endpoint.


        **Partial sends are merged, never replaced.** Send what you have;
        nothing you sent earlier is wiped by a later call. That ends once the
        verification has been filed — a payment in `UNDER_REVIEW`, `VERIFIED`,
        `READY_FOR_SETTLEMENT` or `SETTLED` refuses further sends.


        **An unclassified payment accepts only `business_model` and
        `purpose_code`**, and they must travel together. Nothing else can be
        validated until a checklist claims the payment.


        **Completion is automatic.** Once nothing is outstanding the set is run
        through any verification the payment needs — PAN verification, the
        sender-to-account-holder match, the TCS recomputation and the LRS
        counter posting. Pass `finalize: false` to stage without triggering it.


        **The response carries `outstanding`** — the codes still owed after this
        write. You do not need a second call to learn what is left.


        **PSP callers must send `X-Merchant-ID`.**
      parameters:
        - name: payment_id
          in: path
          required: true
          schema:
            type: string
          description: UID of the payment the details are for.
          example: PR6938527534
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                fields:
                  type: object
                  description: >-
                    Answers keyed by checklist code, e.g. `{"remitter_pan":
                    "ABCPK1234F", "buyer_city": "Bengaluru"}`. Values are
                    strings, numbers or booleans. Dates are `YYYY-MM-DD`;
                    amounts (`principal`, `collected_tcs`) are decimal strings
                    in rupees. An unknown key is a 400 rather than a silent drop
                    — a typo you never hear about would leave the payment
                    waiting forever for a field you believe you sent. Omit a key
                    rather than sending null or an empty string; a blank value
                    is also a 400.
                  additionalProperties: true
                  example:
                    buyer_name: Acme Imports Pvt Ltd
                    buyer_city: Bengaluru
                    invoice_number: INV-2026-0041
                    invoice_date: '2026-08-01'
                documents:
                  type: array
                  description: >-
                    Documents by reference, or waivers. Each entry names exactly
                    one of `ref` and `waiver_reason`; sending both, neither, or
                    the same code twice in one call is a 400.
                  items:
                    type: object
                    required:
                      - code
                    properties:
                      code:
                        type: string
                        description: >-
                          The checklist code this document answers, as named by
                          the verification webhook or GET
                          /pg/payments/{payment_id}/verification/. The codes are
                          configuration and are revised over time — read them
                          rather than hardcoding them.
                        example: invoice
                      ref:
                        type: string
                        description: >-
                          A `ref` returned by Upload Document. Send this or
                          `waiver_reason`, never both.
                        example: a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d
                      waiver_reason:
                        type: string
                        description: >-
                          Why this document is not being supplied. Only accepted
                          on items whose `waivable` is true.
                        example: Destination is visa-free for this passport
                finalize:
                  type: boolean
                  default: true
                  description: >-
                    Whether to run a complete LRS set through the verification
                    gateway. Never forces an incomplete one through.
                linked_payment_id:
                  type: string
                  nullable: true
                  description: >-
                    The earlier payment this one tops up — the buyer was short,
                    or paid the TCS separately. Resolved against your own
                    payments; a link that cannot be resolved is refused. Read by
                    the call that files, so send it with the call that completes
                    the set.
                  example: PR6938527534
                reason:
                  type: string
                  nullable: true
                  enum:
                    - REMAINING_AMOUNT
                    - TCS_PAYMENT
                  description: >-
                    Why the two payments are linked; an audit label on the link.
                    `REMAINING_AMOUNT` — covering a principal shortfall.
                    `TCS_PAYMENT` — paying the TCS separately. Only valid
                    together with `linked_payment_id`.
                  example: REMAINING_AMOUNT
            example:
              fields:
                buyer_name: Acme Imports Pvt Ltd
                buyer_city: Bengaluru
                invoice_number: INV-2026-0041
                invoice_date: '2026-08-01'
              documents:
                - code: invoice
                  ref: a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d
              finalize: true
      responses:
        '200':
          description: >-
            Details received. The body says where the payment now stands and
            what is still owed.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  message:
                    type: string
                    example: Verification details received
                  data:
                    type: object
                    required:
                      - payment_id
                      - status
                      - outstanding
                    properties:
                      payment_id:
                        type: string
                        description: The payment these details were recorded against.
                        example: PR6938527534
                      status:
                        type: string
                        enum:
                          - incomplete
                          - complete
                          - in_review
                          - action_required
                        description: >-
                          Lower-case, always one of four. `incomplete` —
                          something is still owed; `outstanding` names it.
                          `complete` — nothing is outstanding and nothing was
                          filed (you passed `finalize: false`, or this checklist
                          is not an LRS one and needs no gateway handoff).
                          `in_review` — the set was complete, the gateway took
                          it, and it passed. `action_required` — the set was
                          complete and filed, and the gateway did not pass the
                          payment. It never means your details were discarded.
                        example: incomplete
                      outstanding:
                        type: array
                        items:
                          type: string
                        description: >-
                          The codes still owed after this write — the same codes
                          you would get by filtering the GET on `satisfied:
                          false`. Empty when nothing is.
                        example:
                          - invoice_number
                          - invoice
              examples:
                incomplete:
                  summary: incomplete — something is still owed
                  description: >-
                    A partial send. `outstanding` is the list; you do not need a
                    second call to read it.
                  value:
                    success: true
                    message: Verification details received
                    data:
                      payment_id: PR6938527534
                      status: incomplete
                      outstanding:
                        - invoice_number
                        - invoice_date
                        - invoice
                in_review:
                  summary: in_review — the payment is with us
                  description: >-
                    Everything the checklist asks for was sent, the set went
                    through the verification gateway, and it passed. Nothing
                    further to send.
                  value:
                    success: true
                    message: Verification details received
                    data:
                      payment_id: PR6938527534
                      status: in_review
                      outstanding: []
                action_required:
                  summary: action_required — the gateway did not pass it
                  description: >-
                    An empty `outstanding` with this status is not a
                    contradiction: the checklist is satisfied, the gateway
                    refused. The verdict arrives as an LRS_VERIFICATION_NEEDED
                    event with the conclusion folded into the relevant entry's
                    message. No event at all means the handoff itself did not
                    land — repeat the same request.
                  value:
                    success: true
                    message: Verification details received
                    data:
                      payment_id: PR6938527534
                      status: action_required
                      outstanding: []
                complete:
                  summary: complete — staged, not filed
                  description: >-
                    The checklist is satisfied but nothing went to the gateway:
                    either you passed `finalize: false`, or this payment's
                    checklist is not an LRS one.
                  value:
                    success: true
                    message: Verification details received
                    data:
                      payment_id: PR6938527534
                      status: complete
                      outstanding: []
        '400':
          description: >-
            Invalid request — an unknown code, a blank value, a misplaced
            field/document code, an unusable document reference, a duplicate
            document code, or a waiver on a document that cannot be waived.
            Every offending code is named in `error.details`, so one call
            reports every problem at once.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/v3_ErrorResponse'
              example:
                success: false
                error:
                  code: 40359
                  message: Invalid LRS request.
                  details:
                    buyer_citty: Not a requirement of this payment's checklist.
                    invoice: This is a document code; send it under 'documents'.
                    ticket: Sent more than once in this call.
        '404':
          description: >-
            No such payment for this merchant. The same answer whether the
            payment does not exist or belongs to someone else — the endpoint
            never confirms another merchant's payment id.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/v3_ErrorResponse'
              example:
                success: false
                error:
                  code: ERR_PAYMENT_005
                  message: Payment not found
                  details: {}
        '409':
          description: >-
            This payment's verification has already been filed, so its details
            can no longer be changed. Staging closes once `settlement_status`
            reaches `UNDER_REVIEW`, `VERIFIED`, `READY_FOR_SETTLEMENT` or
            `SETTLED` — read it from the GET before sending.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/v3_ErrorResponse'
              example:
                success: false
                error:
                  code: 40360
                  message: Payment is not in a state that accepts verification details.
                  details:
                    detail: >-
                      This payment's verification has already been filed; its
                      details can no longer be changed here.
        '500':
          description: Unexpected processing failure.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/v3_ErrorResponse'
      security:
        - clientAuth: []
          clientSecretAuth: []
          merchantAuth: []
          apiVersionHeader: []
components:
  schemas:
    v3_ErrorResponse:
      type: object
      required:
        - success
        - error
      properties:
        success:
          type: boolean
          description: Indicates if the request was successful
        error:
          $ref: '#/components/schemas/v3_ErrorDetails'
    v3_ErrorDetails:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: Error code (e.g., ERR_ORDER_002)
        message:
          type: string
          description: Error message
        details:
          type: object
          description: Detailed validation error information with field-specific errors
          additionalProperties:
            type: string
            description: Error message for the specific field
  securitySchemes:
    clientAuth:
      type: apiKey
      name: X-Client-ID
      in: header
      description: >-
        **Client Application ID** - Your unique application identifier used to
        authenticate API requests. You can find your Client ID in the Developer
        Settings section of the merchant dashboard.
      x-displayName: Client ID
      x-example: your-client-id
    clientSecretAuth:
      type: apiKey
      name: X-Client-Secret
      in: header
      description: >-
        **Client Secret Key** - Your secret key used alongside the Client ID for
        secure authentication. Keep this confidential and never expose it in
        client-side code. Available in the Developer Settings section of the
        merchant dashboard.
      x-displayName: Client Secret
      x-example: your-client-secret
    apiVersionHeader:
      type: apiKey
      name: X-API-Version
      in: header
      description: >-
        **API Version** - Specifies which version of the API to use (e.g.,
        '1.X.X', '2.X.X', or '3.X.X'). This header allows you to control which
        API version your integration uses. Default version information is
        available in the Developer Settings.
      x-displayName: API Version
      x-example: 3.0.0
    merchantAuth:
      type: apiKey
      name: X-Merchant-ID
      in: header
      description: >-
        **Merchant Identifier** - The unique ID for the merchant account. This
        is required for PSP (Payment Service Provider) merchants who manage
        multiple merchant accounts. You can find merchant IDs in the Merchant
        Management section of the dashboard.
      x-displayName: Merchant ID
      x-example: your-merchant-id

````