Pay
Checkout Link

Accepting Payments via Checkout Link

Learn when and how to accept payments using hosted checkout links


Payload checkout links provide a secure, hosted payment experience for your customers. By generating a link, you can redirect customers to complete payment without embedding checkout UI in your application. Customers complete payment on a Payload-hosted page and are redirected back to your application upon completion with payment status.

Prerequisites

Before integrating checkout links, it's helpful to learn about the following topics.


When to Use Checkout Links


Use checkout links when you need a simple way to accept payments without embedding checkout UI directly in your application. Checkout links are ideal for programmatic flows where you redirect customers to complete payment on a secure, Payload-hosted page, then receive them back in your application with payment status.

By using checkout links, PCI compliance and sensitive payment data handling are managed automatically. The hosted page ensures secure collection of card and bank account details in a compliant environment—removing that responsibility from your application.

Common use cases

  • Multi-Step Workflows: Send users to payment page as part of onboarding or purchase flows
  • No-Code Payment Collection: Accept payments without building custom checkout UI
  • Programmatic Payment Initiation: Generate payment links dynamically based on business logic
  • Third-Party Integrations: Enable payment collection from systems with limited extensibility that support redirects

Generating a Checkout Link

Creating a checkout link is a two-step process: create an intent with the checkout_link type, then redirect your customer to the returned URL to complete payment.

Generate a basic checkout link

Create a simple checkout link with an amount and description.

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
from flask import Flask, redirect, jsonify
 
app = Flask(__name__)
 
@app.route('/create-checkout', methods=['POST'])
def create_checkout():
    # Create a checkout link intent
    intent = pl.Intent.create(
        type='checkout_link',
        checkout_link={
            'payment_template': {
                'amount': 100.00,
                'description': 'Order #12345',
                'receiver': {
                    'account_id': 'acct_receiver123'
                }
            },
            'redirects': {
                'completed_url': 'https://yourapp.com/payment-complete',
                'return_url': 'https://yourapp.com/cart'
            }
        }
    )
 
    # Redirect customer to checkout
    return redirect(intent.url)

This example creates an intent with:

  1. type='checkout_link' tells Payload to generate a hosted checkout page
  2. checkout_link.payment_template configures the payment details (amount, description, receiver)
  3. checkout_link.redirects defines where customers go after payment or if they return

The response includes a url field that contains the secure checkout link. Redirect your customer to this URL to complete payment on the hosted page.

Generate a link for an existing customer

If you have an existing customer account, pass the account_id to pre-populate customer information.

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
from flask import Flask, redirect, request
 
app = Flask(__name__)
 
@app.route('/create-checkout/<account_id>', methods=['POST'])
def create_checkout(account_id):
    # Create a checkout link for an existing customer
    intent = pl.Intent.create(
        type='checkout_link',
        checkout_link={
            'payment_template': {
                'amount': 100.00,
                'description': 'Order #12345',
                'receiver': {
                    'account_id': 'acct_receiver123'
                },
                'sender': {
                    'account_id': account_id
                }
            },
            'redirects': {
                'completed_url': 'https://yourapp.com/payment-complete',
                'return_url': 'https://yourapp.com/cart'
            }
        }
    )
 
    # Redirect customer to checkout
    return redirect(intent.url)

This example:

  1. Passes sender.account_id to link the payment to an existing customer
  2. Allows the customer to use saved payment methods
  3. Automatically associates the payment with the customer record

Use this pattern when you have customer accounts and want to provide a faster checkout experience with saved payment methods.


Configuring Checkout Options

Checkout links support the same configuration options as the Checkout Plugin, allowing you to control payment methods, fees, billing fields, and UI behavior.

Payment Methods

Control which payment types are available during checkout:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Configure allowed payment methods
intent = pl.Intent.create(
    type='checkout_link',
    checkout_link={
        'checkout_options': {
            'allowed_methods': {
                'card': 'enabled',
                'bank_account': 'disabled',
                'apple_pay': 'enabled',
                'google_pay': 'enabled'
            }
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        },
        'redirects': {
            'completed_url': 'https://yourapp.com/payment-complete',
            'return_url': 'https://yourapp.com/cart'
        }
    }
)
 
checkout_url = intent.url

This configuration:

  • Enables card payments (Visa, Mastercard, American Express, Discover)
  • Disables bank account payments
  • Enables Apple Pay for customers on Apple devices
  • Enables Google Pay for customers on Android devices

Convenience Fees

Add a convenience fee to offset payment processing costs:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Add a convenience fee
intent = pl.Intent.create(
    type='checkout_link',
    checkout_link={
        'checkout_options': {
            'enable_sender_fee': 'enabled'
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        },
        'redirects': {
            'completed_url': 'https://yourapp.com/payment-complete',
            'return_url': 'https://yourapp.com/cart'
        }
    }
)
 
checkout_url = intent.url

This adds a convenience fee based on your processing account's fee configuration. The fee is calculated and displayed to the customer before they complete the payment.

Editable Amount

Allow customers to change the payment amount, useful for donations or tips:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Allow customers to change the payment amount
intent = pl.Intent.create(
    type='checkout_link',
    checkout_link={
        'checkout_options': {
            'allow_editable_amount': True
        },
        'payment_template': {
            'amount': 50.00,
            'description': 'Donation',
            'receiver': {
                'account_id': 'acct_receiver123'
            }
        },
        'redirects': {
            'completed_url': 'https://yourapp.com/payment-complete',
            'return_url': 'https://yourapp.com/donate'
        }
    }
)
 
checkout_url = intent.url

This configuration:

  • Displays the initial amount as $50
  • Allows customers to change the amount to any value they choose
  • Useful for donation forms, tips, or customer-determined payments

Autopay Enrollment

Enable the Autopay toggle to let customers enroll in automatic billing:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Enable Autopay enrollment
intent = pl.Intent.create(
    type='checkout_link',
    checkout_link={
        'checkout_options': {
            'show_autopay_toggle': True
        },
        'payment_template': {
            'amount': 100.00,
            'description': 'Order #12345',
            'receiver': {
                'account_id': 'acct_receiver123'
            },
            'sender': {
                'account_id': 'acct_customer456',
                'method': {
                    'account_defaults': {
                        'paying': 'payments'
                    }
                }
            }
        },
        'redirects': {
            'completed_url': 'https://yourapp.com/payment-complete',
            'return_url': 'https://yourapp.com/cart'
        }
    }
)
 
checkout_url = intent.url

This configuration:

  • Shows an Autopay enrollment checkbox in the checkout form
  • Automatically saves the payment method and links it to the customer account
  • Sets the payment method as the default for future automatic payments

Handling Payment Completion

After a customer completes payment via a checkout link, they are redirected to the completed_url you specified when creating the intent. The URL includes a pl_transaction_id query parameter containing the transaction ID.

Redirect URL Structure

When a customer completes payment, they are redirected to:

https://yourapp.com/payment-complete?pl_transaction_id=txn_abc123def456

Processing the Transaction ID

Handle the redirect and retrieve transaction details:

import payload
from flask import Flask, request, render_template
 
pl = payload.Session('secret_key_3bW9...', api_version='v2')
app = Flask(__name__)
 
 
@app.route('/payment-complete')
def payment_complete():
    # Extract transaction ID from query parameter
    transaction_id = request.args.get('pl_transaction_id')
 
    # Fetch the transaction details
    transaction = pl.Transaction.get(transaction_id)
 
    # Verify the payment status
    if transaction.status == 'processed':
        # Payment successful
        # Update your database, fulfill the order, send confirmation email
        print(f'Payment successful: {transaction.id}')
        print(f'Amount: ${transaction.amount}')
 
        return render_template('success.html', transaction=transaction)
    else:
        # Payment not completed
        return render_template('payment_pending.html')

This example:

  1. Extracts the pl_transaction_id from the query parameters
  2. Fetches the transaction details from the Payload API
  3. Verifies the payment status
  4. Updates your database and fulfills the order

Tracking Payment Status

After sharing a checkout link, if needed you can monitor its status and completion through webhooks and API queries.

Webhook Events

Subscribe to the processed webhook trigger to track successful payments. Configure a webhook with:

  • trigger: processed - Monitors successful payment completion
  • reference_object: transaction - Specifies the object type being monitored
  • url: Your endpoint URL to receive webhook notifications

Example webhook handler:

from flask import Flask, request
 
app = Flask(__name__)
 
@app.route("/webhooks/payload", methods=["POST"])
def handle_webhook():
    webhook = request.json
 
    if webhook["trigger"] == "processed" and webhook["triggered_on"]["type"] == "payment":
        transaction = webhook["triggered_on"]
 
        print("Payment successful:", transaction["id"])
        # Update order status in your database
        # Send confirmation email
 
    return "OK", 200

Query Intent Status

You can also retrieve the intent to check its status:

import payload
pl = payload.Session('secret_key_3bW9...', api_version='v2')
 
# Query the intent status
intent = pl.Intent.get('intent_abc123')
 
print(f'Intent ID: {intent.id}')
print(f'Intent Type: {intent.type}')
print(f'Checkout URL: {intent.url}')
 
# Check if payment was completed
if hasattr(intent, 'transaction_id') and intent.transaction_id:
    print(f'Payment completed: {intent.transaction_id}')
 
    # Fetch transaction details
    transaction = pl.Transaction.get(intent.transaction_id)
    print(f'Transaction status: {transaction.status}')
else:
    print('Payment not yet completed')

Schema Reference


The following fields are available when configuring the Checkout Link intent. For complete API reference documentation, see Intent API Reference.

Intent Configuration

Configuration options passed when creating the checkout link intent on your backend:

checkout_link
object
Configuration for the checkout link intent. Use this type to generate a hosted payment page URL that you can redirect customers to. The checkout link provides a complete, hosted checkout experience on a Payload-hosted page. Returns a URL that you can redirect customers to or send via email. Required when type is checkout_link.
checkout_options
object
Checkout form configuration including which payment methods are allowed, convenience fees, address requirements, and UI options. Controls the behavior and appearance of the hosted checkout page. Uses implicit values if not specified.
allow_editable_amount
boolean
When set to true, allows the customer to change the payment amount in the checkout form. Useful for donation forms, tip jars, or scenarios where the customer determines the amount. When false, the amount is fixed and cannot be modified by the customer.
allowed_methods
object
Configuration for which payment methods are available in the checkout. Controls whether customers can pay with cards, bank accounts, digital wallets (Apple Pay, Google Pay), or Plaid. Use this to restrict or enable specific payment options based on your business needs.
apple_pay
enum[string]
Controls whether Apple Pay digital wallet is available in the checkout. Set to "enabled" to allow Apple Pay payments or "disabled" to hide this payment option. Apple Pay provides a fast, secure checkout experience for customers on Apple devices.
Values: enabled, disabled
bank_account
enum[string]
Controls whether bank account payments are allowed in the checkout. Possible values: "default" (use processing account settings), "enabled" (allow bank account payments), or "disabled" (disallow bank account payments). When enabled, customers can pay by bank with their bank account.
Values: default, enabled, disabled
card
enum[string]
Controls which card payments are allowed in the checkout. Possible values: "default" (use processing account settings), "enabled" (allow all card types), "disabled" (disallow card payments), "credit" (only credit cards), or "debit" (only debit cards). When enabled, customers can pay with their payment cards.
Values: default, enabled, disabled, credit, debit
google_pay
enum[string]
Controls whether Google Pay digital wallet is available in the checkout. Set to "enabled" to allow Google Pay payments or "disabled" to hide this payment option. Google Pay provides a fast, secure checkout experience for customers on supported devices.
Values: enabled, disabled
plaid
enum[string]
Controls whether Plaid instant bank account verification is available in the checkout. Set to "enabled" to allow customers to connect their bank accounts via Plaid or "disabled" to use Payload's built-in verification methods.
Values: enabled, disabled
enable_sender_fee
enum[string]
Controls whether a convenience fee is charged to the payer. Possible values: "default" (use processing account settings), "enabled" (charge fee for all payment methods), "disabled" (no convenience fee), "card" (charge fee only for card payments), or "bank_account" (charge fee only for bank account payments). Convenience fees help offset processing costs by passing them to the payer.
Values: default, enabled, disabled, card, bank_account
require_full_billing_address
boolean
When set to true, requires the customer to provide their complete billing address (street, city, state, postal code, country) during checkout. When false, only postal code and country may be required. Full addresses improve fraud prevention and address verification (AVS) but increase checkout friction.
show_autopay_toggle
boolean
When set to true, adds a checkbox allowing the customer to set the payment method as their default for automatic billing. Useful for subscription and recurring billing scenarios where future payments should be charged automatically. The customer opts in by checking the box.
show_disclosure
boolean
When set to true, displays terms, conditions, and disclosure information in the checkout form. Use this to show important legal text, refund policies, or transaction terms that customers should be aware of before completing payment. Helps with compliance and transparency.
show_keep_active_toggle
boolean
When set to true, adds a checkbox allowing the customer to save the payment method for future use. When checked, the payment method will be stored securely and can be used for subsequent payments without re-entering details. Improves convenience for returning customers.
show_payment_method_preview
boolean
When set to true, displays a graphical preview of the payment method (card image, bank icon) above the checkout form. Provides visual confirmation of the payment method being used, improving user experience and reducing errors.
payment_template
object
Payment details and configuration including amount, receiver, sender, invoice allocations, and transaction settings. Defines what payment is being collected and from/to whom. Uses implicit values if not specified.
amount
number (double)
The payment amount to charge. This is the total amount that will be charged to the customer, before any convenience fees if enabled.
attrs
object
Custom attributes for the transaction as a JSON object. Use this to store additional metadata or custom fields specific to your application. These attributes are stored with the transaction and can be retrieved later for reporting or integration purposes.
clearing_timing
enum[string]Immutable
The clearing speed for this transaction, determining how quickly funds are made available to the recipient. Instant clearing makes funds available immediately, same_day within the same business day, and next_day by the following business day. Defaults to next_day if not specified. Same-day and instant are only available in certain circumstances.
Values: instant, same_day, next_day
description
string
Description of what the payment is for. This appears on receipts, transaction records, and bank statements. Examples include "Order #1234", "Monthly subscription", or "Invoice payment". Helps customers identify the transaction.
funding_timing
enum[string]Immutable
The funding speed for this transaction, determining how quickly the merchant or processing account receives settlement of funds. Standard timing follows normal settlement schedules, while rapid timing accelerates the funding process for faster access to funds. Defaults to standard if not specified. Rapid and instant funding only available in certain circumstances.
Values: standard, instant, rapid
invoice_allocations
array
List of invoices that this payment should be applied to. When provided, the payment will be allocated across these invoices, reducing their outstanding balances. Use this for paying multiple invoices with a single payment or specifying which invoice a payment is for.
order_number
string
Custom order or transaction number for this payment. Use this to link the payment to an order in your system or to provide a customer-facing transaction reference. Providing this value ensures duplicate protection is applied per order; otherwise, duplicate protection applies across payments without an order reference.
receiver
object
Information about who will receive the payment and optionally the specific payment method for receiving funds. The receiver is the party being paid.
account_id
string
The unique identifier of the account that will receive this payment. This may represent a merchant, service provider, vendor, or other authorized recipient of funds. Required to identify who is receiving the funds.
method_id
string
The unique identifier of the payment method where funds will be deposited. If not specified, the receiver account's default method will be used.
sender
object
Information about who is making the payment. Includes the account and optionally pre-filled payment method details. The sender is the party being charged.
account_id
string
The unique identifier of the account making the payment. This is the payer who will be charged or the party who will fund the transfer. Used to associate the payment with the correct account.
method
object
Pre-filled values for the payment method that will be created or used for this payment. Allows you to set defaults like billing address, account holder name, or transfer type. These values populate the checkout form or are used when creating the payment method.
account_defaults
object
Default transaction types that this payment method will be used for. Controls whether the payment method is the default for paying or funding transactions, and which specific types of transactions it applies to.
funding
enum[string]
Controls which funding transaction types this payment method can be used for. Possible values: "all" (use for all funding transactions), "deposits" (use only for receiving deposits), or "withdraws" (use only for withdrawals). Determines the default usage for receiving funds.
Values: all, deposits, withdraws
paying
enum[string]
Controls which paying transaction type this payment method will be the default for. Possible values: "all" (use for all paying transactions), "payments" (use only for sending payments), or "payouts" (use only for receiving payouts). Determines the default usage for sending funds. If the account default is set for payments, that payment method will be used for any automatic invoice payments.
Values: all, payments, payouts
account_holder
string
Pre-filled name of the account holder for the payment method. For bank accounts, this is the name on the account. For cards, this is the cardholder name. When provided, this value will be used to populate the form.
account_id
string
The ID of the account that will own this payment method. Links the payment method to a specific customer or processing account. Used to associate the payment method with the correct account when it is created.
bank_account
object
Configuration specific to bank account payment methods. Contains bank account-specific settings such as the currency.
currency
enum[string]
The currency for bank account transactions. Must be either "USD" (US Dollars) or "CAD" (Canadian Dollars). Determines the currency for transactions using this bank account.
Values: USD, CAD
billing_address
object
Pre-filled billing address for the payment method. When provided, these values will be used to populate the address fields in the checkout form. Customers may be able to edit these values depending on checkout configuration.
address_line_1
string
Street address of the address
address_line_2
string
Unit number of the address
city
string
City of the company
country_code
string
Country code of the address
postal_code
string
Postal code of the address
state_province
string
State of the address
id
string
The unique identifier of an existing payment method to update. When provided, the form will be used to update the payment method, such as revalidating the CVV, updating the expiration date, or changing the billing address.
transfer_type
enum[string]
The transfer capabilities for this payment method. Possible values: "send_only" (can only send payments/fund payouts), "receive_only" (can only receive payouts/deposits), or "two_way" (can both send and receive). Controls how the payment method can be used for transactions.
Values: send_only, receive_only, two_way
source
enum[string]Immutable
The method by which this transaction was initiated or captured. This indicates whether the transaction was manually keyed, initiated via digital wallets like Google Pay or Apple Pay, or processed as a check conversion.
Values: keyed, googlepay, applepay, check
status
object
Target status configuration for the payment transaction. Controls whether the payment should be authorized only or immediately processed and captured.
value
enum[string]
The desired final status for the transaction. Possible values: "authorized" (authorize the payment but do not capture funds yet, useful for delayed capture), or "processed" (immediately process and capture the payment). Determines whether the payment is captured immediately or held for later capture.
Values: authorized, processed
transfers
array
List of transfer allocations for splitting a payment across multiple receivers. Each transfer specifies a receiver and an amount, allowing a single payment to be distributed to multiple accounts. Useful for marketplace or platform payments where funds need to be split between multiple parties.
redirects
object
Redirect URLs for the checkout flow. Defines where customers go after completing payment or if they cancel/return during checkout. Both URLs are required for checkout links.
completed_url
string
The URL where customers will be redirected after successfully completing the payment. This should be a page in your application that confirms the payment and provides next steps. Required for checkout links.
return_url
string
The URL where customers will be redirected if they click the return/back button during checkout. This should take them back to your application, typically to the shopping cart or order page. Required for checkout links.

Next Steps

Enhance your checkout implementation


Create Customer Accounts

Create customer accounts to enable saved payment methods and faster checkout.

Handle Refunds

Process refunds and voids for cancellations and returns after payments complete.

Monitor Payment Events

Subscribe to webhook notifications to track payment status and automate order fulfillment.


Related articles