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

# Request a Payment Payload

> Tell us what you want to move — where from, where to, and how much — and we
answer with everything the payment needs: the fields to send on
`create-transaction`, what the objects behind those fields must carry, our
fee, and a **reference** that pins the amount.

- `source_type`: `wallet`, `bank` (the user's linked bank account), `card`
  (the user's saved card) or `vba` (the user's virtual bank account).
- `destination_type`: `wallet`, `bank` (a bank in the US: the user's own
  linked bank or a payee's bank destination — the id you send on
  `create-transaction` says which), `bank_international` (a payee's bank
  abroad — send `destination_country` and `destination_currency` too) or
  `merchant` (a card-acquiring account).
- `amount` is what the payment will move. `create-transaction` takes no
  amount of its own; it comes off the reference.

`fields` is the whole body `create-transaction` takes, keyed by field name,
mandatory fields first. Each entry says whether it is `required` and lists
its `requirements` — the details the object behind that id must already have
for this payment to go through (for example a payee's last name, or an
address in the destination country), as `{field, label}` items. `required`
is about that one field. Some fields are alternatives to each other: each of
those is `required: false` and names its `one_of` group, and the top-level
`one_of` map states the rule — send exactly one field of each group. A
`bank` payout has one such group: `bank_account_id` (the user's own bank — a
`transfer`) or `payee_destination_id` (a payee — a `send`). A field marked
`companion_of` goes only with that alternative: `payee_address_id` rides with
`payee_destination_id`, and is `required` when the route chosen for the
payment asks for the payee's address (some routes for a `bank` payout do, as
every payout abroad does). Where
`destinations_supported` is true, `destinations` is listed too: the optional
alternative to the single destination field, for splitting the amount across
wallets. Create or update the objects first, then call `create-transaction`
with the reference.

`fee` is our fee for this payment. It is **not** taken out of the amount —
it is billed to your platform on the monthly invoice. For wallet → wallet it
is `null` here and settled at `create-transaction`, because it depends on
whether the two wallets belong to the same user (`payment_type`).

**Name the objects when you know them.** `bank_account_id` (the user's
linked bank on a deposit from `bank` or a withdrawal to `bank`) and
`payee_destination_id` (the destination of a `bank` or `bank_international`
payout) are optional here, and worth sending: the payload is then worked out
for that exact bank or destination, so a route that cannot serve it is never
offered and `create-transaction` will not send you back for a new payload.
Always send `payee_destination_id` for an email destination. An id sent for
a movement that does not take it is refused (`field_not_allowed`), as are
both ids of a `bank` payout together; one that is not yours is `404`; and
when no route can serve the objects at all the answer is
`payload_incomplete` with `missing` — the same answer `create-transaction`
gives, one call earlier. Without them the payload is worked out from the
types alone, exactly as before — a `bank` payout then reports
`payment_type: null`, settled by the id `create-transaction` receives.

The reference is single-use and valid until `expires_at` (30 minutes).
Sending the same `idempotency_key` again returns the same reference, even
once it has expired — a fresh quote needs a fresh key.



## OpenAPI

````yaml POST /v1/platform/payments/request-payload
openapi: 3.1.0
info:
  title: Finogate Platform API v1
  version: 0.1.0
servers:
  - url: https://api-sandbox.finogates.com
    description: Sandbox
  - url: https://api.finogates.com
    description: Production
security: []
tags:
  - name: auth
  - name: users
  - name: payees
  - name: verification
  - name: bank accounts
  - name: card processing
  - name: digital-assets
  - name: international
  - name: fees
  - name: onboarding
  - name: Redirect URLs
  - name: pending-applications
  - name: wallets
  - name: payments
  - name: document mailing
  - name: merchant onboarding
  - name: catalog
  - name: webhooks
  - name: screening
  - name: Platform - File Scanning
  - name: phone-numbers
  - name: sms
  - name: calls
  - name: listings
  - name: Card Transfers
  - name: Accounting
  - name: embed-tokens
paths:
  /v1/platform/payments/request-payload:
    post:
      tags:
        - payments
      summary: Request the payload for a payment
      description: >-
        Tell us what you want to move — where from, where to, and how much — and
        we

        answer with everything the payment needs: the fields to send on

        `create-transaction`, what the objects behind those fields must carry,
        our

        fee, and a **reference** that pins the amount.


        - `source_type`: `wallet`, `bank` (the user's linked bank account),
        `card`
          (the user's saved card) or `vba` (the user's virtual bank account).
        - `destination_type`: `wallet`, `bank` (a bank in the US: the user's own
          linked bank or a payee's bank destination — the id you send on
          `create-transaction` says which), `bank_international` (a payee's bank
          abroad — send `destination_country` and `destination_currency` too) or
          `merchant` (a card-acquiring account).
        - `amount` is what the payment will move. `create-transaction` takes no
          amount of its own; it comes off the reference.

        `fields` is the whole body `create-transaction` takes, keyed by field
        name,

        mandatory fields first. Each entry says whether it is `required` and
        lists

        its `requirements` — the details the object behind that id must already
        have

        for this payment to go through (for example a payee's last name, or an

        address in the destination country), as `{field, label}` items.
        `required`

        is about that one field. Some fields are alternatives to each other:
        each of

        those is `required: false` and names its `one_of` group, and the
        top-level

        `one_of` map states the rule — send exactly one field of each group. A

        `bank` payout has one such group: `bank_account_id` (the user's own bank
        — a

        `transfer`) or `payee_destination_id` (a payee — a `send`). A field
        marked

        `companion_of` goes only with that alternative: `payee_address_id` rides
        with

        `payee_destination_id`, and is `required` when the route chosen for the

        payment asks for the payee's address (some routes for a `bank` payout
        do, as

        every payout abroad does). Where

        `destinations_supported` is true, `destinations` is listed too: the
        optional

        alternative to the single destination field, for splitting the amount
        across

        wallets. Create or update the objects first, then call
        `create-transaction`

        with the reference.


        `fee` is our fee for this payment. It is **not** taken out of the amount
        —

        it is billed to your platform on the monthly invoice. For wallet →
        wallet it

        is `null` here and settled at `create-transaction`, because it depends
        on

        whether the two wallets belong to the same user (`payment_type`).


        **Name the objects when you know them.** `bank_account_id` (the user's

        linked bank on a deposit from `bank` or a withdrawal to `bank`) and

        `payee_destination_id` (the destination of a `bank` or
        `bank_international`

        payout) are optional here, and worth sending: the payload is then worked
        out

        for that exact bank or destination, so a route that cannot serve it is
        never

        offered and `create-transaction` will not send you back for a new
        payload.

        Always send `payee_destination_id` for an email destination. An id sent
        for

        a movement that does not take it is refused (`field_not_allowed`), as
        are

        both ids of a `bank` payout together; one that is not yours is `404`;
        and

        when no route can serve the objects at all the answer is

        `payload_incomplete` with `missing` — the same answer
        `create-transaction`

        gives, one call earlier. Without them the payload is worked out from the

        types alone, exactly as before — a `bank` payout then reports

        `payment_type: null`, settled by the id `create-transaction` receives.


        The reference is single-use and valid until `expires_at` (30 minutes).

        Sending the same `idempotency_key` again returns the same reference,
        even

        once it has expired — a fresh quote needs a fresh key.
      operationId: create_payment_request_v1_platform_payments_request_payload_post
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PaymentRequestCreate'
        required: true
      responses:
        '201':
          description: Payload described
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CommonResponse'
              example:
                status_code: 201
                data:
                  reference: 3f9c1b2a-9d84-4e15-8c26-0b7a5d3e1f90
                  status: open
                  expires_at: '2026-09-11T10:30:00Z'
                  source_type: wallet
                  destination_type: bank
                  payment_type: send
                  amount: 250
                  currency: USD
                  fee: 3
                  destinations_supported: false
                  fields:
                    reference:
                      required: true
                      requirements: []
                    idempotency_key:
                      required: true
                      requirements: []
                    wallet_id:
                      required: true
                      requirements: []
                    payee_destination_id:
                      required: true
                      requirements:
                        - field: bank_account_number
                          label: Bank account number
                        - field: last_name
                          label: Last name
                    user_id:
                      required: false
                      requirements: []
                    payment_category:
                      required: false
                      requirements: []
                    metadata:
                      required: false
                      requirements: []
                    from_hold:
                      required: false
                      requirements: []
                    notify_recipient:
                      required: false
                      requirements: []
                query_generated_time: 1712847600000
        '403':
          description: product_not_enabled
          content:
            application/json:
              examples:
                product_not_enabled:
                  summary: product_not_enabled (error_code 1105)
                  value:
                    status_code: 403
                    data:
                      detail: >-
                        The product this payment needs is not enabled for your
                        platform.
                      code: product_not_enabled
                      error_code: 1105
                    query_generated_time: 1750000000000
              schema:
                $ref: '#/components/schemas/CodedErrorResponse'
        '422':
          description: >-
            movement_unsupported, destination_country_required,
            destination_currency_required, field_not_allowed,
            payload_incomplete, payment_not_available
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CodedErrorResponse'
              examples:
                movement_unsupported:
                  summary: movement_unsupported (error_code 1102)
                  value:
                    status_code: 422
                    data:
                      detail: >-
                        This combination of source_type and destination_type is
                        not available on this endpoint.
                      code: movement_unsupported
                      error_code: 1102
                    query_generated_time: 1750000000000
                destination_country_required:
                  summary: destination_country_required (error_code 1103)
                  value:
                    status_code: 422
                    data:
                      detail: >-
                        destination_country is required when destination_type is
                        bank_international.
                      code: destination_country_required
                      error_code: 1103
                    query_generated_time: 1750000000000
                destination_currency_required:
                  summary: destination_currency_required (error_code 1104)
                  value:
                    status_code: 422
                    data:
                      detail: >-
                        destination_currency is required when destination_type
                        is bank_international.
                      code: destination_currency_required
                      error_code: 1104
                    query_generated_time: 1750000000000
                field_not_allowed:
                  summary: field_not_allowed (error_code 1112)
                  value:
                    status_code: 422
                    data:
                      detail: The body carries a field this payment does not take.
                      code: field_not_allowed
                      error_code: 1112
                    query_generated_time: 1750000000000
                payload_incomplete:
                  summary: payload_incomplete (error_code 1111)
                  value:
                    status_code: 422
                    data:
                      detail: >-
                        The payload does not carry everything this payment
                        needs. See fields for what is missing.
                      code: payload_incomplete
                      error_code: 1111
                    query_generated_time: 1750000000000
                payment_not_available:
                  summary: payment_not_available (error_code 1106)
                  value:
                    status_code: 422
                    data:
                      detail: >-
                        This payment cannot be carried right now. Check the
                        amount and currency, or try again later.
                      code: payment_not_available
                      error_code: 1106
                    query_generated_time: 1750000000000
        '503':
          description: payment_request_unavailable
          content:
            application/json:
              examples:
                payment_request_unavailable:
                  summary: payment_request_unavailable (error_code 1107)
                  value:
                    status_code: 503
                    data:
                      detail: >-
                        A payment request cannot be prepared for this movement
                        at the moment. Please try again later or contact
                        support.
                      code: payment_request_unavailable
                      error_code: 1107
                    query_generated_time: 1750000000000
              schema:
                $ref: '#/components/schemas/CodedErrorResponse'
      security:
        - _AuthenticatedBearer: []
components:
  schemas:
    PaymentRequestCreate:
      properties:
        source_type:
          type: string
          maxLength: 40
          title: Source Type
          description: >-
            Where the money comes from: `wallet`, `bank` (the user's linked bank
            account), `card` (the user's saved card) or `vba` (the user's
            virtual bank account).
          examples:
            - wallet
        destination_type:
          type: string
          maxLength: 40
          title: Destination Type
          description: >-
            Where the money goes: `wallet`, `bank` (a bank in the US — the
            user's own linked bank, named by `bank_account_id`, or a payee's
            bank destination, named by `payee_destination_id`),
            `bank_international` (a payee's bank abroad) or `merchant` (a
            card-acquiring account).
          examples:
            - bank
        amount:
          anyOf:
            - type: number
              exclusiveMinimum: 0
            - type: string
              pattern: ^(?!^[-+.]*$)[+-]?0*\d*\.?\d*$
          title: Amount
          description: >-
            The amount to move, in major units, at most 2 decimal places. This
            is the amount the payment will move — `create-transaction` takes no
            amount of its own.
          examples:
            - 250
        currency:
          type: string
          maxLength: 3
          minLength: 3
          title: Currency
          description: ISO-4217 code of the amount. Defaults to `USD`.
          default: USD
          examples:
            - USD
        delivery_speed:
          type: string
          enum:
            - standard
            - same_day
            - instant
          title: Delivery Speed
          description: >-
            How fast the money should land. `standard` is the default for every
            movement; `same_day` (same-day ACH) and `instant` (real-time
            payment, bank destinations only) are offered where the movement
            supports them and are priced and timed on their own terms. A speed
            the movement cannot deliver is refused with `speed_not_offered`; a
            payment is never silently downgraded.
          default: standard
          examples:
            - standard
        destination_country:
          anyOf:
            - type: string
              maxLength: 2
              minLength: 2
            - type: 'null'
          title: Destination Country
          description: >-
            ISO-3166 alpha-2 country the money lands in. Required when
            `destination_type` is `bank_international`; ignored otherwise.
          examples:
            - MX
        destination_currency:
          anyOf:
            - type: string
              maxLength: 3
              minLength: 3
            - type: 'null'
          title: Destination Currency
          description: >-
            ISO-4217 code the recipient is paid in. Required when
            `destination_type` is `bank_international`; ignored otherwise.
          examples:
            - MXN
        bank_account_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Bank Account Id
          description: >-
            Optional. The user's linked bank account this payment will use — the
            source of a deposit from `bank`, or the destination of a withdrawal
            to `bank` (the user's own bank; a `transfer`). When given, the
            payload is worked out for that bank: a route that cannot serve it is
            not offered, and `create-transaction` will not send you back for a
            new payload. Refused (`field_not_allowed`) for a movement that takes
            no bank account, or alongside `payee_destination_id`.
          examples:
            - 33333333-3333-3333-3333-333333333333
        payee_destination_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: Payee Destination Id
          description: >-
            Optional. The payee destination a `bank` or `bank_international`
            payout will pay (a `send`). When given, the payload is worked out
            for that destination — send it whenever you know it, and always for
            an email destination. Refused (`field_not_allowed`) for a movement
            that takes no payee destination, or alongside `bank_account_id`.
          examples:
            - 22222222-2222-2222-2222-222222222222
        idempotency_key:
          type: string
          maxLength: 120
          minLength: 1
          title: Idempotency Key
          description: >-
            A unique value you pick for this request. Sending the same key again
            returns the same reference — even after it has expired — so a fresh
            quote needs a fresh key.
          examples:
            - quote-2026-09-11-0001
      additionalProperties: false
      type: object
      required:
        - source_type
        - destination_type
        - amount
        - idempotency_key
      title: PaymentRequestCreate
      description: Request body for ``POST /v1/platform/payments/request-payload``.
    CommonResponse:
      properties:
        status_code:
          type: integer
          title: Status Code
          description: HTTP status code for the response.
        data:
          title: Data
          description: Payload or error details.
        query_generated_time:
          type: integer
          title: Query Generated Time
          description: >-
            UTC timestamp (milliseconds since epoch) when response was
            generated.
      type: object
      required:
        - status_code
        - data
        - query_generated_time
      title: CommonResponse
      description: |-
        Standard response wrapper for single-object responses and errors.

        Generic over the payload type. A route that declares
        ``CommonResponse[SomeModel]`` gets the real ``data`` schema rendered in
        OpenAPI/Swagger; a bare ``CommonResponse`` leaves ``data`` untyped.
    CodedErrorResponse:
      properties:
        status_code:
          type: integer
          title: Status Code
          description: HTTP status code for the response.
        data:
          $ref: '#/components/schemas/CodedErrorBody'
          description: Payload or error details.
        query_generated_time:
          type: integer
          title: Query Generated Time
          description: >-
            UTC timestamp (milliseconds since epoch) when response was
            generated.
      type: object
      required:
        - status_code
        - data
        - query_generated_time
      title: CodedErrorResponse
      description: Standard envelope wrapping a :class:`CodedErrorBody`.
    CodedErrorBody:
      properties:
        detail:
          type: string
          title: Detail
          description: Human-readable error message.
        code:
          type: string
          title: Code
          description: Stable string error code — the canonical value to branch on.
        error_code:
          type: integer
          title: Error Code
          description: >-
            Numeric custom error code from the Finogate registry. Unique per
            condition and stable forever.
      type: object
      required:
        - detail
        - code
        - error_code
      title: CodedErrorBody
      description: >-
        The ``data`` payload of a coded-error response.


        Condition-specific extras (e.g. ``remaining_time``) may also appear;
        only

        the always-present fields are typed here.
  securitySchemes:
    _AuthenticatedBearer:
      type: oauth2
      flows:
        password:
          scopes: {}
          tokenUrl: /v1/platform/auth/token

````