Search Overlay

Use Case 2: Withdrawals

This use case allows you to pay money to a consumer who has already made a payment on your webstore using Pay by Bank.

Consumer experience

This is the journey for a consumer making a withdrawal.

Select Pay by Bank Select bank account The withdrawal is completed

Implementation

Call the following endpoints in sequence:

  1. /paymenthub/v1/paymenthandles

    (transactionType: VERIFICATION)

    Initializes the verification process, which is a mandatory step in order to complete the subsequent steps. 

  2. /paymenthub/v1/verifications

    Returns the list of bank accounts linked to the consumer.

  3. /paymenthub/v1/paymenthandles

    (transactionType: STANDALONE_CREDIT)

    Initializes the withdrawal by validating whether the request can be actioned (by checking if you have sufficient balance for example). It provides you with a payment handle token that you can then use to complete the payment.

  4. /paymenthub/v1/standalonecredits

    Moves money to the consumer and debits your balance.

NOTE: For code examples and detailed explanations of the parameters, refer to the Payments API Reference.

STEP 1: Call paymenthandles for verifications

  • Call endpoint /paymenthub/v1/paymenthandles

    • transactionType:  VERIFICATION
    • paymentType:  PAY_BY_BANK
  • Pass the required parameters in the payByBank object.

  • If this is a new consumer, pass the required parameters in the billingDetails and profile objects.

  • Paysafe creates a payment handle and returns our standard gateway response, indicating either a positive or negative outcome:

    Happy path: this is a returning consumer

    Outcome Paysafe
    HTTP
    Status Code
    LPM Error
    Code/ Message
    Can be
    simulated?
    How to
    simulate?
    Payment
    handle
    status
    Next
    action
    The consumer
    exists in Pay
    by Bank.

    201

     

    YES

    Submit any
    consumerId
    that you have
    already linked.

    PAYABLE

    Go to step 2 to
    retrieve the array
    of bank accounts
    for the consumer.

    Happy path: this is a new consumer

    Outcome Paysafe
    HTTP
    Status Code
    Paysafe
    Error
    Code
    Paysafe
    Error
    Message
    LPM
    Error
    Code
    Can be
    simulated?
    How to
    simulate?
    Payment
    handle
    status
    Next
    action
    This is a new
    consumer who
    has not previously
    used Pay by Bank.
    201   USER_NOT_EXIST   YES Submit any
    consumerId
    that you have
    not already
    linked.
    FAILED Go to step 3
    to link a bank
    account for
    the consumer.
  • The payment handle status depends on the outcome of the request:

    • For positive scenarios, the payment handle is created with status PAYABLE.
    • For negative scenarios, the payment handle is created with status FAILED.

STEP 2: Call verifications

  • Call endpoint /paymenthub/v1/verifications using the paymentHandleToken.

    • The payment handle status changes to COMPLETED.

  • Paysafe returns our verifications response, indicating that the request status is COMPLETED and providing a paymentHandleToken for each registered bank account.

  • Store the token (payByBank.achBankAccounts.paymentHandleToken) for later use.

    payByBank.achBankAccounts.paymentHandleToken is a unique identifier for each bank account of the consumer and does not change. You subsequently use it to create a single-use payment handle token, which is used to make payments and withdrawals for each unique transaction.

     

    Happy path: Paysafe returns the consumer's linked bank accounts

    Outcome Paysafe
    HTTP
    Status Code
    LPM Error
    Code/ Message
    Can be
    simulated?
    How to
    simulate?
    Payment
    handle
    status
    Next
    action
    Paysafe returns a
    list of up to 4 linked
    bank accounts for
    the existing
    consumer.

    201

     

    YES

    Submit any
    consumerId
    that you have
    already linked.

    COMPLETED

    Go to step 3 to
    initiate a withdrawal
    using the selected
    bank account.

STEP 3: Call paymenthandles for withdrawals

  • Call endpoint /paymenthub/v1/paymenthandles

    • transactionType: STANDALONE_CREDIT
    • paymentType: PAY_BY_BANK
  • Pass the required parameters:

    • If this is a new consumer, pass the required parameters in the payByBank, profile and billingDetails objects.
    • If this is a returning consumer, pass the required parameters in the payByBank object only.
  • Paysafe creates a payment handle and returns our standard gateway response, indicating either a positive or negative outcome:

    Happy path: the returning consumer initiates a withdrawal

    Outcome Paysafe
    HTTP
    Status Code
    LPM Error
    Code/ Message
    Can be
    simulated?
    How to
    simulate?
    Payment
    handle
    status
    Next
    action

    The returning
    consumer initiates a
    withdrawal with
    Pay by Bank,
    using their linked
    bank account.

    201

    N/A

    YES
    (external)

    Submit consumerId and
    ach.paymentHandleToken,
    which you have already
    linked.

    PAYABLE

    Go to step 5 to
    process the
    withdrawal.

  • The payment handle status depends on the outcome of the request:

    • For positive scenarios where this is either a new consumer or a returning consumer who is adding a new bank account, the payment handle is created with status INITIATED.
    • For positive scenarios where an existing consumer is using an existing bank account, the payment handle is created with status PAYABLE.
    • For negative scenarios, the payment handle is created with status FAILED.

STEP 4: Redirect consumer

  • Redirect the consumer to the URL provided in the payment handle response.

    • The payment handle status changes to PROCESSING.
  • The consumer accepts the Terms & Conditions (T&Cs), selects the bank they want to add, and provides the credentials of the bank account to confirm linking it.

    • The payment handle status changes to PAYABLE.
  • Paysafe returns our standard gateway response, indicating either a positive or negative outcome:

    Happy path: the consumer is enrolled and the bank account is successfully added

    Outcome Paysafe
    HTTP
    Status Code
    LPM Error
    Code/ Message
    Can be
    simulated?
    How to
    simulate?
    Payment
    handle
    status
    Next
    action

    The consumer is
    enrolled, and the
    bank account is
    added.

     

     

    YES

    Submit a
    transaction
    with a value
    of <1000 and
    select Custom
    Account Ending
    in 9828
     on the
    redirection page

    PAYABLE

    Go to step 5 to
    process the
    withdrawal.

    Unhappy path: the consumer rejects the Terms & Conditions (T&Cs)

    Outcome Paysafe
    HTTP
    Status Code
    Paysafe
    Error
    Code
    Paysafe
    Error
    Message
    LPM
    Error
    Code
    Can be
    simulated?
    How to
    simulate?
    Payment
    handle
    status
    Next
    action
    The consumer
    rejects the
    T&Cs, so the
    request fails.
            YES Do not
    accept the
    T&Cs on the
    redirection
    page.
    FAILED  
  • The payment handle status depends on the outcome of the request:

    • For positive scenarios, the payment handle status changes to PAYABLE.
    • For negative scenarios, the payment handle status changes to FAILED.

STEP 5: Call standalonecredits

  • Call endpoint /paymenthub/v1/standalonecredits using the paymentHandleToken.

  • Paysafe returns our standard gateway response, indicating either a positive or negative outcome:

    Positive outcome: Happy path

    Outcome Paysafe
    HTTP
    Status Code
    Paysafe
    Error
    Code
    Paysafe
    Error
    Message
    LPM
    Error
    Code
    Can be
    simulated?
    Magic
    Value
    (Amount)

    The request succeeds.

     

    N/A

    N/A

     

    YES
    (external)

     

    Negative outcomes: Unhappy path - the request fails

    Outcome Paysafe
    HTTP
    Status Code
    Paysafe
    Error
    Code
    Paysafe
    Error
    Message
    LPM
    Error
    Code
    Can be
    simulated?
    Magic
    Value
    (Amount)
    The Paysafe token is
    not used within 15
    minutes.
          PAYMENT_HANDLE_EXPIRED YES
    (external)
    Auto triggered
    after 15 mins.
  • The payment handle status depends on the outcome of the request:

    • For positive scenarios, the status first changes to PROCESSING and then to COMPLETED.
    • For negative scenarios, the status changes to FAILED.
    • For negative scenarios where the token expires after 15 minutes, the status changes to EXPIRED.
  • Following a successful withdrawal, the consumer receives email confirmation of the payout.

NOTE: If Overdraft Threshold Protection is enabled during onboarding, a withdrawal request will initially be set to a PENDING status and executed within 15 minutes. If there are insufficient funds in the account, the transaction will remain in PENDING status until enough funds are available for it to be automatically processed. Transactions can remain in PENDING status for up to 7 days. If the account balance is still insufficient after this period, the transaction will be marked as FAILED.

Delayed withdrawal processing

If you need to trigger delayed withdrawals for regulatory compliance, risk checks, or to build a backend process around withdrawals, follow these steps:

  1. When calling the endpoint /paymenthub/v1/standalonecredits/during step 5, include the onHold object with the value set to true in the request body. This will set the standalonecredit status to HELD, with the statusReason as HELD_BY_MERCHANT.
  2. When you have completed your checks and are ready with your final decision about the withdrawal, call the following endpoint:
    PATCH: /paymenthub/v1/standalonecredits/{standaloneCreditId}
    Depending on how you want to proceed, include one of the following options in the request body:
    • To proceed with the withdrawal, set onHold to false.
    • To cancel the withdrawal request, set status to CANCELLED.

NOTE: Transactions will stay in HELD status for up to 15 days. After this period, they will be marked as EXPIRED, with the statusReason set to MERCHANT_NOT_CONFIRMED.