Custom Checkout

Some use-cases require advanced functionality that simply isn’t available via the dashboard. Custom checkouts allow you to access lots of advanced checkout functionality (such as splitting transaction earnings between multiple recipients).

Custom Checkouts Overview

Custom checkouts allow you to access a plethora of additional checkout functionality that isn’t available via our dashboard by standard.

Custom checkouts can be based on an existing product (in which case they will inherit certain properties of that product - unless you override them) or can be completely custom, and not based on any existing product.

The API will return a link to the checkout that you can pass the user to just like any standard checkout link.

API Endpoint

The endpoint for the custom checkout API is: https://vendors.paddle.com/api/2.0/product/generate_pay_link

Send all field as POST to the API endpoint. A list of accepted fields and their meanings is below.

Field Required Description
vendor_id Yes Your Paddle Vendor/Account ID
vendor_auth_code Yes Your Paddle code/token for authenticating with the API
product_id Variable The Paddle Product ID that you want to base this custom checkout on.

This field is optional if setting the other fields required for a checkout to be created.
title Variable The name of the product/ title of the checkout.

This property is required if product_id is not set.
webhook_url Variable A URL that we will call with transaction information upon successful checkout, to allow you to fulfill the purchase.

This property should only be sent if product_id is not set.
prices Variable Price(s) of the checkout for a one-time purchase or initial payment of a subscription.

For paid checkouts, you must specify at least one price, however you can specify up to three in USD, EUR and GBP. See example code below for how to format the contents of this field.

This property is required if product_id is not set.
locale No Force the checkout to a specific locale
recurring_prices No Recurring price(s) of the checkout (excluding the initial payment) if the product_id specified is a subscription.

If you leave this field empty, then the default prices of the Plan will be used.

If this field is provided, you can set the recurring price for any of the currencies of your Plan, but you must always provide the recurring price in the main currency of your Plan.

To override the initial payment and all recurring payment amounts, both prices and recurring_prices must be set.
trial_days No The number of days before Paddle starts charging the customer the recurring price.

If you leave this field empty, the trial days of the Plan will be used.
custom_message No A short message displayed below the product name on the checkout.
coupon_code No A coupon to be applied to the checkout.
image_url No A URL for the product image/ icon displayed on the checkout.
return_url No A URL to redirect to once the checkout is completed.
quantity_variable No Specifies if the user is allowed to alter the quantity of the checkout, accepts 0 or 1 (default: 1).
quantity No Hard set the quantity to a value, this will also prevent it from being changed.
expires No Specifies if the checkout link should expire, the generated checkout URL will be accessible until this date (accepts date in the format 2015-08-05, YYYY-MM-DD)
affiliates No Other Paddle merchants who should receive funds from this checkout. See the section ‘Splitting Funds Between Vendors’ below, for more details.
recurring_affiliate_limit No If the product_id specified is a subscription and affiliates fields are provided, this field will limit the number of times other Paddle vendors will receive funds from the recurring prices. The checkout is included in the limit. See the section ‘Splitting Funds Between Vendors’ below, for more details.
marketing_consent Variable Whether you have gathered consent to market to the customer.

This property is required if customer_email is set and you want to opt the customer into marketing.
customer_email No Pre-fills the customers email on the checkout page, and removes that step.
customer_country No Pre-fills the customers country on the checkout page, and removes that step. The available countries are listed below. Note that the country code should be passed.
customer_postcode No Pre-fills the customers postal code on the checkout page, and removes that step.

N.b. It is highly recommended to pass customer country (above) when setting a postcode.
vat_code No Pre-fills the customer’s VAT registration number.
passthrough No Pre-fills the passthrough of the checkout. This value will be sent back to you via certain webhooks, if enabled.

Full Example Request


<?php
	$data['vendor_id'] = 123;
	$data['vendor_auth_code'] = '456bd...';
	
	$data['title'] = 'Demo Product'; // name of product
	$data['webhook_url'] = 'http://mysite.com/callback'; // URL to call when product is purchased
	
	// You must provide at least one price for the checkout, here we are setting multiple for different currencies.
	$data['prices'] = [
		'USD:10',
		'GBP:12',
		'EUR:9.5'
	];
	
	// Setting some other (optional) data.
	$data['custom_message'] = '100% Money Back Guarantee!';
	$data['return_url'] = 'http://mysite.com/thanks';
	
	// Here we make the request to the Paddle API
	$url = 'https://vendors.paddle.com/api/2.0/product/generate_pay_link';
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
	$response = curl_exec($ch);
	
	// And handle the response...
	$data = json_decode($response);
	if($data->success) {
		echo "Success! Checkout URL:".$data->response->url;
	} else {
		echo "Your request failed with error: ".$data->error->message;
	}
?>

Bash Example



curl -X POST \
     -d 'vendor_id=123' \
     -d 'vendor_auth_code=456bd...' \
     -d 'title=Demo Product' \
     -d 'webhook_url=http://mysite.com/callback' \
     -d 'prices[0]=USD:16.7' \
     -d 'prices[1]=GBP:12' \
     -d 'prices[2]=EUR:9.5' \
     -d 'custom_message=100% Money Back Guarantee!' \
     -d 'return_url=http://mysite.com/thanks' \
https://vendors.paddle.com/api/2.0/product/generate_pay_link

Example Response

{
    "success": true,
    "response": {
        "url": "https://checkout.paddle.com/checkout/custom/eyJ0IjoiUHJvZ……."
  }
}

Splitting Funds Between Vendors

One of the more useful features of custom checkouts is the ability to split earnings from a transaction between multiple Paddle accounts. This is done by specifying the percentage of the transaction that will be attributed to each account, with the remaining percentage being attributed to the account owner (the vendor making the API request).

This is done by passing the parameter affiliates to the API containing vendor_id’s and commission percentages for each participant. See the example below for a better illustration.


<?php
	$data['vendor_id'] = 123;
	$data['vendor_auth_code'] = '456bd...';
	
	$data['title'] = 'Demo Product'; // name of product
	$data['webhook_url'] = 'http://mysite.com/callback'; // URL to call when product is purchased
	
	// You must provide at least one price for the checkout, here we are setting multiple for different currencies.
	$data['prices'] = [
		'USD:10',
		'GBP:12',
		'EUR:9.5'
	];
	
	// This is where we specify the other participants that we wish to split earnings with
	$data['affiliates'] = [
		'456:0.15', // Vendor 456 gets 15%
		'789:0.15' // Vendor 789 gets 15%
	]; // You (requester) gets 70%
	
	// Here we make the request to the Paddle API
	$url = 'https://vendors.paddle.com/api/2.0/product/generate_pay_link';
	$ch = curl_init($url);
	curl_setopt($ch, CURLOPT_POST, true);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
	$response = curl_exec($ch);
	
	// And handle the response...
	$data = json_decode($response);
	if($data->success) {
		echo "Success! Checkout URL:".$data->response->url;
	} else {
		echo "Your request failed with error: ".$data->error->message;
	}
?>

Bash Example



curl -X POST \
     -d 'vendor_id=123' \
     -d 'vendor_auth_code=456bd...' \
     -d 'title=Demo Product' \
     -d 'webhook_url=http://mysite.com/callback' \
     -d 'prices[0]=USD:16.7' \
     -d 'prices[1]=GBP:12' \
     -d 'prices[2]=EUR:9.5' \
     -d 'affiliates[0]=456:0.15' \
     -d 'affiliates[1]=789:0.15' \
     https://vendors.paddle.com/api/2.0/product/generate_pay_link

Example Response

{
    "success": true,
    "response": {
        "url": "https://checkout.paddle.com/checkout/custom/eyJ0IjoiUHJvZ……."
  }
}

Limit Splitting Recurring Funds Between Vendors

If the product specified in the product_id field is a subscription, the completed checkout will result in recurring payments charged to the customer. As usual, this will result in earnings for you, the requester. But if you have specified affiliates, then by default every recurring payment will also result in earnings for the other specified Paddle merchants. To limit the number of times this split occurs, you can specify the recurring_affiliate_limit field. The specified limit must be at least 1 and specifies the number of recurring payments (including the checkout payment) for which the other Paddle merchants will receive funds. After the number of payments, you will receive the full earnings of the recurring payments.

See the example below for the usage of this parameter.


<?php
    $data[‘vendor_id’] = 123;
    $data[‘vendor_auth_code’] = ‘456bd...’;
    
    // The fictional Plan has a billing interval of 1 month.
    $data['product_id'] = 123456;
    $data['recurring_affiliate_limit'] = 2;
    $data['affiliates'] = [
        '456:0.15', // Vendor 456 will receive 15% for 2 payments, including the checkout and the first recurring payment.
        '789:0.15' // Vendor 789 will also receive 15% for 2 payments, including the checkout and the first recurring payment.
    ];
    
    // Here we make the request to the Paddle API
    $url = 'https://vendors.paddle.com/api/2.0/product/generate_pay_link';
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
    $response = curl_exec($ch);
    
    // And handle the response...
    $data = json_decode($response);
    if ($data->success) {
        echo "Success! Checkout URL:" . $data->response->url;
    } else {
        echo "Your request failed with error: " . $data->error->message;
    }

Bash Example



curl -X POST \
     -d 'vendor_id=123' \
     -d 'vendor_auth_code=456bd...' \
     -d 'product_id=123456' \
     -d 'affiliates[0]=456:0.15' \
     -d 'affiliates[1]=789:0.15' \
     -d 'recurring_affiliate_limit=2' \
     -https://vendors.paddle.com/api/2.0/product/generate_pay_link

Example Response

{
    "success": true,
    "response": {
        "url": "https://checkout.paddle.com/checkout/custom/eyJ0IjoiUHJvZ……."
  }
}

Opening Custom Checkouts with Paddle.js (Overlay)

Checkouts created with the Custom Checkout API can be opened using Paddle.js in the same way a normal checkout would.

Instead of specifying a data-product/product within either the checkout button, or Javascript call, you instead specify data-override/override as in the examples below.

Button Example

<a href="#!" class="paddle_button" data-override="https://checkout.paddle.com/custom/abc123...">Buy Now!</a>

Javascript Example

Paddle.Checkout.open({
  override: 'https://checkout.paddle.com/custom/abc123...'
});

Note: You must have completed the Paddle.js Basic Setup for the above examples to work correctly.

Supported Locales

The following locales are accepted values to be passed with the locale field within a Custom Checkout API request.

  • en : English
  • de : German
  • fr : French
  • es : Spanish
  • pt : Portuguese
  • nl : Dutch
  • ru : Russian
  • it : Italian
  • ja : Japanese
  • pl : Polish
  • zh-Hans : Chinese Simplified
  • ar : Arabic

Recognised Countries

The following countries are accepted values to be passed with the customer_country field within a Custom Checkout API request.

  • AF: Afghanistan
  • AL: Albania
  • DZ: Algeria
  • AS: American Samoa
  • AD: Andorra
  • AO: Angola
  • AI: Anguilla
  • AG: Antigua and Barbuda
  • AR: Argentina
  • AM: Armenia
  • AW: Aruba
  • AU: Australia
  • AT: Austria
  • AZ: Azerbaijan
  • BS: Bahamas
  • BH: Bahrain
  • BD: Bangladesh
  • BB: Barbados
  • BY: Belarus
  • BE: Belgium
  • BZ: Belize
  • BJ: Benin
  • BM: Bermuda
  • BT: Bhutan
  • BO: Bolivia
  • BA: Bosnia and Herzegovina
  • BW: Botswana
  • BV: Bouvet Island
  • BR: Brazil
  • IO: Brit. Indian Ocean
  • VG: British Virgin Islands
  • BN: Brunei Darussalam
  • BG: Bulgaria
  • BF: Burkina Faso
  • BI: Burundi
  • KH: Cambodia
  • CM: Cameroon
  • CA: Canada
  • CV: Cape Verde
  • KY: Cayman Islands
  • CF: Central African Republic
  • TD: Chad
  • CL: Chile
  • CN: China
  • CX: Christmas Island
  • CC: Cocos Islands
  • CO: Colombia
  • KM: Comoros
  • CG: Congo
  • CK: Cook Islands
  • CR: Costa Rica
  • CI: Cote D’Ivoire
  • HR: Croatia
  • CU: Cuba
  • CW: Curaçao
  • CY: Cyprus
  • CZ: Czech Republic
  • DK: Denmark
  • DJ: Djibouti
  • DM: Dominica
  • DO: Dominican Republic
  • EC: Ecuador
  • EG: Egypt
  • SV: El Salvador
  • GQ: Equatorial Guinea
  • ER: Eritrea
  • EE: Estonia
  • ET: Ethiopia
  • FK: Falkland Islands
  • FO: Faroe Islands
  • FJ: Fiji
  • FI: Finland
  • FR: France
  • GF: French Guiana
  • PF: French Polynesia
  • TF: French Southern Terr.
  • GA: Gabon
  • GM: Gambia
  • GE: Georgia
  • DE: Germany
  • GH: Ghana
  • GI: Gibraltar
  • GR: Greece
  • GL: Greenland
  • GD: Grenada
  • GP: Guadeloupe
  • GU: Guam
  • GT: Guatemala
  • GG: Guernsey
  • GN: Guinea
  • GW: Guinea-Bissau
  • GY: Guyana
  • HT: Haiti
  • HM: Heard/ Mcdonald Islands
  • VA: Holy See/ Vatican City
  • HN: Honduras
  • HK: Hong Kong
  • HU: Hungary
  • IS: Iceland
  • IN: India
  • ID: Indonesia
  • IR: Iran
  • IQ: Iraq
  • IE: Ireland
  • IL: Israel
  • IT: Italy
  • JM: Jamaica
  • JP: Japan
  • JE: Jersey
  • JO: Jordan
  • KZ: Kazakhstan
  • KE: Kenya
  • KI: Kiribati
  • KW: Kuwait
  • KG: Kyrgyzstan
  • LA: Lao People’s DR
  • LV: Latvia
  • LB: Lebanon
  • LS: Lesotho
  • LR: Liberia
  • LY: Libyan Arab Jamahiriya
  • LI: Liechtenstein
  • LT: Lithuania
  • LU: Luxembourg
  • MO: Macao
  • MK: Macedonia
  • MG: Madagascar
  • MW: Malawi
  • MY: Malaysia
  • MV: Maldives
  • ML: Mali
  • MT: Malta
  • MH: Marshall Islands
  • MQ: Martinique
  • MR: Mauritania
  • MU: Mauritius
  • YT: Mayotte
  • MX: Mexico
  • FM: Micronesia
  • MD: Moldova
  • MC: Monaco
  • MN: Mongolia
  • ME: Montenegro
  • MS: Montserrat
  • MA: Morocco
  • MZ: Mozambique
  • MM: Myanmar
  • NA: Namibia
  • NR: Nauru
  • NP: Nepal
  • NL: Netherlands
  • AN: Netherlands Antilles
  • NC: New Caledonia
  • NZ: New Zealand
  • NI: Nicaragua
  • NE: Niger
  • NG: Nigeria
  • NU: Niue
  • NF: Norfolk Island
  • KP: North Korea
  • MP: Northern Mariana Islands
  • NO: Norway
  • OM: Oman
  • PK: Pakistan
  • PW: Palau
  • PS: Palestinian Territory
  • PA: Panama
  • PG: Papua New Guinea
  • PY: Paraguay
  • PE: Peru
  • PH: Philippines
  • PN: Pitcairn
  • PL: Poland
  • PT: Portugal
  • PR: Puerto Rico
  • QA: Qatar
  • RS: Republic of Serbia
  • RE: Reunion
  • RO: Romania
  • RU: Russian Federation
  • RW: Rwanda
  • GS: S. Georgia/ Sandwich Islands
  • SH: Saint Helena
  • KN: Saint Kitts and Nevis
  • LC: Saint Lucia
  • PM: Saint Pierre and Miquelon
  • VC: Saint Vincent/ Grenadines
  • WS: Samoa
  • SM: San Marino
  • ST: Sao Tome and Principe
  • SA: Saudi Arabia
  • SN: Senegal
  • SC: Seychelles
  • SL: Sierra Leone
  • SG: Singapore
  • SK: Slovakia
  • SI: Slovenia
  • SB: Solomon Islands
  • SO: Somalia
  • ZA: South Africa
  • KR: South Korea
  • ES: Spain
  • LK: Sri Lanka
  • SD: Sudan
  • SR: Suriname
  • SJ: Svalbard and Jan Mayen
  • SZ: Swaziland
  • SE: Sweden
  • CH: Switzerland
  • SY: Syrian Arab Republic
  • TW: Taiwan
  • TJ: Tajikistan
  • TZ: Tanzania
  • TH: Thailand
  • TL: Timor-Leste
  • TG: Togo
  • TK: Tokelau
  • TO: Tonga
  • TT: Trinidad and Tobago
  • TN: Tunisia
  • TR: Turkey
  • TM: Turkmenistan
  • TC: Turks and Caicos Islands
  • TV: Tuvalu
  • VI: U.S. Virgin Islands
  • UG: Uganda
  • UA: Ukraine
  • AE: United Arab Emirates
  • GB: United Kingdom
  • US: United States
  • UM: United States (M.O.I.)
  • UY: Uruguay
  • UZ: Uzbekistan
  • VU: Vanuatu
  • VE: Venezuela
  • VN: Viet Nam
  • WF: Wallis and Futuna
  • EH: Western Sahara
  • YE: Yemen
  • ZM: Zambia
  • ZW: Zimbabwe

Questions about Paddle?

If you need any help regarding your Paddle integration, please get in touch with our Customer Success team using the form below.