Bill for non-catalog items
Charge for an item without adding it to your product catalog by passing price or product attributes when working with a transaction or a subscription.
As well as creating transactions for items in your product catalog, you can create transactions for non-catalog items. This is useful for one-off or bespoke items that are specific to that transaction. For example, you may agree a custom price with an enterprise customer.
You may also like to bill for non-catalog items if you work with products where the price changes often, or where you need to manage your product catalog outside of Paddle. For example, games companies typically manage their product catalog centrally because they need to work with app stores.
How it works
Transactions calculate and capture revenue in Paddle. To bill for an item, you add it to a transaction. There are two ways you can do this:
Using your product catalog
Create products and prices in Paddle, then pass prices IDs to transactions or Paddle.js to bill for them.
- Manage items using the product catalog in Paddle.
- Items can be reused across transactions easily.
- Useful for companies who sell a set of digital products at the same price points.
For example:
- SaaS companies who sell subscription plans and addons. Prices may vary by country, but items remain the same.
- Companies who sell a selection of digital products or software licences where the items remain the same.
Billing for non-catalog items
Pass price and product attributes directly to a transaction when creating or updating to bill for them.
- Manage items using your own product database.
- Items are specific to a transaction.
- Useful for companies with lots of items, or where item prices may change a lot.
For example:
- Games companies who maintain a large catalog of items and may show different prices to different user segments.
- eBook sellers, where publishers set prices and they may change daily.
How do non-catalog items relate to catalog items?
A complete product in Paddle is made up of a product entity that describes the item, and a related price entity that describes how much and how often a product is billed.
You can add non-catalog items to a transaction where:
Only the price is custom.
This is great where the products you offer stay the same, but you might offer bespoke pricing from time to time. Your non-catalog price relates an existing catalog product entity in Paddle, sharing the same product name, image, and tax category.
Both the price and the product are custom.
Where you manage your product catalog outside of Paddle, you can create entirely custom products. Your item uses a non-catalog price and a non-catalog product.
When you create or update a transaction with non-catalog items, Paddle creates a price entity and (optionally) a related product entity. They have a Paddle ID as normal, meaning you can use the get a product or get a price operations to work with them, but they're not added to your product catalog.
This means they're not returned by default when listing products or prices, and they're not shown in the Paddle dashboard.
Non-catalog price and product entities have a type
of custom
, so you can differentiate between entities in your catalog.
Subscriptions
This guide walks through adding non-catalog items to transactions, but you can also:
You can configure non-catalog items for a subscriptions in the same way as transactions.
Before you begin
Set your default payment link
To create a transaction, you'll need to first:
- Set your default payment link under Paddle > Checkout > Checkout settings > Default payment link.
- Get your default payment link domain approved, if you're working with the live environment.
We recommend starting the domain approval early in your integration process, so your domains are approved for when you're ready to go live.
Bill for a non-catalog price for an existing product
You can add a non-catalog price for an existing product in your catalog to a transaction. In this case, the product you're billing for is the same, but you charge a specific price for it.
Add a custom price for a product to a transaction using the API in three steps:
Build a request that includes a list of items, where your item includes a price object.
Preview your transaction (optional)
Preview your transaction. Paddle returns a preview of the transaction, including tax and localized pricing. You may like to present this information to a customer, depending on your workflow.
Send the request to create your transaction. Paddle creates it. Its status is
draft
orready
depending on the information you supplied.
Build request
Build an array of items
, with an object containing a price
object and quantity
for each item.
Relate your custom price to an existing product in your catalog by including product_id
with the Paddle ID of a product entity.
Recurring items on a transaction must have the same billing interval. For example, you can't have a transaction with some prices that are billed monthly and some products that are billed annually.
You may also include existing items by passing an object containing a price_id
and quantity
.
If you like, you can include customer, address, and business information to create a transaction that's ready for billing.
For a full list of the fields you can send when creating a transaction, see: Create a transaction
List of items to charge for.
Quantity of this item on the transaction.
Price object for a non-catalog item to charge for. Include a product_id
to relate this non-catalog price to an existing catalog price.
Request
This example creates a draft transaction for a one-time non-catalog item. It's for an existing product, related using the product_id
field.
12345678910111213141516171{
2 "items": [
3 {
4 "quantity": 1,
5 "price": {
6 "product_id": "pro_01he5kwnnvgdv2chtpgavk2rf8",
7 "description": "New user price (FTUE)",
8 "name": "Invigaron Berries welcome price",
9 "unit_price": {
10 "amount": "999",
11 "currency_code": "USD"
12 }
13 }
14 }
15 ],
16 "currency_code": "USD"
17}
Request
This example creates a draft invoice for a 50-user enterprise plan. It's for an existing product, related using the product_id
field. It includes a customer and an address.
Collection mode is manual
, meaning this transaction is an invoice. Once issued, Paddle sends an invoice to the customer for manual collection.
12345678910111213141516171819201{
2 "items": [
3 {
4 "quantity": 50,
5 "price": {
6 "product_id": "pro_01gsz4vmqbjk3x4vvtafffd540",
7 "description": "Globex annual 2024",
8 "name": "Annual (per seat) deal for Globex",
9 "billing_cycle": {
10 "interval": "year",
11 "frequency": 1
12 },
13 "unit_price": {
14 "amount": "50000",
15 "currency_code": "USD"
16 }
17 }
18 }
19 ],
20 "customer_id": "ctm_01h8441jn5pcwrfhwh78jqt8hk",
Preview request
Send a POST
request to the /transactions/preview
endpoint with the request you built.
Response
If successful, Paddle returns a preview of the new transaction entity.
12345678910111213141516171819201{
2 "data": {
3 "customer_id": null,
4 "address_id": null,
5 "business_id": null,
6 "currency_code": "USD",
7 "address": null,
8 "customer_ip_address": null,
9 "discount_id": null,
10 "items": [
11 {
12 "price": {
13 "id": null,
14 "description": "New user price (FTUE)",
15 "type": "custom",
16 "name": "Invigaron Berries welcome price",
17 "product_id": "pro_01he5kwnnvgdv2chtpgavk2rf8",
18 "billing_cycle": null,
19 "trial_period": null,
20 "tax_mode": "account_setting",
Send request
Send a POST
request to the /transactions
endpoint with the request you built.
Response
If successful, Paddle responds with a copy of the new transaction entity.
The created transaction is draft
. You can pass this transaction to a checkout to capture customer and address information, and collect for payment.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01hj3rtynv8rdn1zbcjk42z05j",
4 "status": "draft",
5 "customer_id": null,
6 "address_id": null,
7 "business_id": null,
8 "custom_data": null,
9 "origin": "api",
10 "collection_mode": "automatic",
11 "subscription_id": null,
12 "invoice_id": null,
13 "invoice_number": null,
14 "billing_details": null,
15 "billing_period": null,
16 "currency_code": "USD",
17 "discount_id": null,
18 "created_at": "2023-12-20T14:07:25.454915616Z",
19 "updated_at": "2023-12-20T14:07:25.454915616Z",
20 "billed_at": null,
Response
If successful, Paddle responds with a copy of the new transaction entity.
The created invoice is ready
, since it includes all the required fields for it to be issued. Issue it to send it the customer.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01hj3ryktw234aj7s0wt5sp69g",
4 "status": "ready",
5 "customer_id": "ctm_01h8441jn5pcwrfhwh78jqt8hk",
6 "address_id": "add_01h848pep46enq8y372x7maj0p",
7 "business_id": null,
8 "custom_data": null,
9 "origin": "api",
10 "collection_mode": "manual",
11 "subscription_id": null,
12 "invoice_id": null,
13 "invoice_number": null,
14 "billing_details": {
15 "enable_checkout": false,
16 "payment_terms": {
17 "interval": "day",
18 "frequency": 14
19 },
20 "purchase_order_number": "PO-2400",
Bill for a non-catalog price and a non-catalog-product
You can add a non-catalog price for a non-catalog product in your catalog to a transaction. This is useful if you manage your product catalog outside of Paddle, or you want to sell something entirely bespoke.
Add a custom price for a custom product to a transaction using the API in three steps:
Build a request that includes a list of items, where your item includes a price object with a product object.
Preview your transaction (optional)
Preview your transaction. Paddle returns a preview of the transaction, including tax and localized pricing. You may like to present this information to a customer, depending on your workflow.
Send the request to create your transaction. Paddle creates it. Its status is
draft
orready
depending on the information you supplied.
Build request
Build an array of items
, with an object containing a price
object and quantity
for each item.
Include a product
object in your price
object, with information about the product for this custom price.
Recurring items on a transaction must have the same billing interval. For example, you can't have a transaction with some prices that are billed monthly and some products that are billed annually.
You may also include existing items by passing an object containing a price_id
and quantity
.
If you like, you can include customer, address, and business information to create a transaction that's ready for billing.
For a full list of the fields you can send when creating a transaction, see: Create a transaction
List of items to charge for.
Quantity of this item on the transaction.
Price object for a non-catalog item to charge for. Include a product
object to create a non-catalog product for this non-catalog price.
Request
This example creates a ready transaction for a one-time non-catalog item. It's for a non-catalog product.
12345678910111213141516171819201{
2 "items": [
3 {
4 "quantity": 1,
5 "price": {
6 "description": "New user price (FTUE)",
7 "name": "Welcome price",
8 "unit_price": {
9 "amount": "999",
10 "currency_code": "USD"
11 },
12 "product": {
13 "name": "Invigaron Berries Hoard",
14 "tax_category": "standard",
15 "description": "Start the game with 20 extra seconds play time!"
16 }
17 }
18 }
19 ],
20 "currency_code": "USD"
Request
This example creates a ready transaction for a recurring non-catalog item. It's for a non-catalog product.
12345678910111213141516171819201{
2 "items": [
3 {
4 "quantity": 1,
5 "price": {
6 "description": "Battle pass",
7 "name": "Monthly",
8 "billing_cycle": {
9 "interval": "month",
10 "frequency": 1
11 },
12 "unit_price": {
13 "amount": "1099",
14 "currency_code": "USD"
15 },
16 "product": {
17 "name": "Invigaron VIP pass",
18 "tax_category": "standard",
19 "description": "Lock in 200x Invigaron Berries a month, plus faster gem spawns, exclusive skins, and early access to the leaderboard."
20 }
Preview request
Send a POST
request to the /transactions/preview
endpoint with the request you built.
Response
If successful, Paddle returns a preview of the new transaction entity.
12345678910111213141516171819201{
2 "data": {
3 "customer_id": null,
4 "address_id": null,
5 "business_id": null,
6 "currency_code": "USD",
7 "address": null,
8 "customer_ip_address": null,
9 "discount_id": null,
10 "items": [
11 {
12 "price": {
13 "id": null,
14 "description": "New user price (FTUE)",
15 "type": "custom",
16 "name": "Welcome price",
17 "product_id": null,
18 "billing_cycle": null,
19 "trial_period": null,
20 "tax_mode": "account_setting",
Response
If successful, Paddle returns a preview of the new transaction entity.
12345678910111213141516171819201{
2 "data": {
3 "customer_id": null,
4 "address_id": null,
5 "business_id": null,
6 "currency_code": "USD",
7 "address": null,
8 "customer_ip_address": null,
9 "discount_id": null,
10 "items": [
11 {
12 "price": {
13 "id": null,
14 "description": "Battle pass",
15 "type": "custom",
16 "name": "Monthly",
17 "product_id": null,
18 "billing_cycle": {
19 "interval": "month",
20 "frequency": 1
Send request
Send a POST
request to the /transactions
endpoint with the request you built.
Response
If successful, Paddle responds with a copy of the new transaction entity.
The created transaction is draft
. You can pass this transaction to a checkout to capture customer and address information, and collect for payment.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01hj3s8yt41c6kaqm8rx9zfgtf",
4 "status": "draft",
5 "customer_id": null,
6 "address_id": null,
7 "business_id": null,
8 "custom_data": null,
9 "origin": "api",
10 "collection_mode": "automatic",
11 "subscription_id": null,
12 "invoice_id": null,
13 "invoice_number": null,
14 "billing_details": null,
15 "billing_period": null,
16 "currency_code": "USD",
17 "discount_id": null,
18 "created_at": "2023-12-20T14:15:04.47996325Z",
19 "updated_at": "2023-12-20T14:15:04.47996325Z",
20 "billed_at": null,
Response
If successful, Paddle responds with a copy of the new transaction entity.
The created transaction is draft
. You can pass this transaction to a checkout to capture customer and address information, and collect for payment.
Paddle automatically creates a subscription for recurring items. Use webhooks to provision your app and create a related record in your backend.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01hj3sct9my6jsx9zt55thzpfw",
4 "status": "draft",
5 "customer_id": null,
6 "address_id": null,
7 "business_id": null,
8 "custom_data": null,
9 "origin": "api",
10 "collection_mode": "automatic",
11 "subscription_id": null,
12 "invoice_id": null,
13 "invoice_number": null,
14 "billing_details": null,
15 "billing_period": null,
16 "currency_code": "USD",
17 "discount_id": null,
18 "created_at": "2023-12-20T14:17:10.858871798Z",
19 "updated_at": "2023-12-20T14:17:10.858871798Z",
20 "billed_at": null,
Update a non-catalog price or product
Non-catalog products and prices are created for specific transactions. They're not considered part of your product catalog. You shouldn't ordinarily need to update them.
Non-catalog products and prices have Paddle IDs, so you can update them using the update a product or update a price operations if needed. For example, you might correct a spelling error in a name
or description
— especially where an item is recurring.
See: Create products and prices
Add a non-catalog item to your catalog
If you find yourself adding similar non-catalog prices or products to transactions, you might like to add a custom item you've previously worked with to your product catalog.
We recommend that you create a new product or price in your catalog where you're adding an item to your standard offering.
You can also get an existing custom price or product using its ID, then change the type to standard
.
Build request
Build a request that includes the type
as standard
.
The type
field exists against both product and price entities.
Type of product or price. Standard products and prices are considered part of your product catalog and are shown on the Paddle dashboard.
Request
1231{
2 "type": "standard"
3}
Send request
Send a PATCH
request to the /products/{product_id}
endpoint or the /prices/{price_id}
endpoint with the request you built.
Paddle ID of the product entity to work with.
Paddle ID of the price entity to work with.
Response
If successful, Paddle returns a copy of the updated product or price entity. The type
is standard
, and it's now considered part of your product catalog.
1234567891011121314151617181{
2 "data": {
3 "id": "pro_01hj3sctbh6r2hyga7qg29dznq",
4 "name": "Invigaron VIP pass",
5 "tax_category": "standard",
6 "type": "standard",
7 "description": "Lock in 200x Invigaron Berries a month, plus faster gem spawns, exclusive skins, and early access to the leaderboard.",
8 "image_url": null,
9 "custom_data": null,
10 "status": "active",
11 "import_meta": null,
12 "created_at": "2023-12-20T14:17:10.769Z",
13 "updated_at": "2023-12-20T14:18:35.093Z"
14 },
15 "meta": {
16 "request_id": "dc625fb7-38b8-47b5-8497-fe51e5c1a2e3"
17 }
18}
Events
transaction.created | Occurs when a transaction is created initially. Other transaction events may follow, depending on the information included with your request. |
price.created | Occurs when a custom price is created. |
product.created | Occurs when a custom product is created. |
Related pages
- Bill for non-catalog items
- How it works
- How do non-catalog items relate to catalog items?
- Subscriptions
- Before you begin
- Set your default payment link
- Bill for a non-catalog price for an existing product
- Build request
- Preview request
- Send request
- Bill for a non-catalog price and a non-catalog-product
- Build request
- Preview request
- Send request
- Update a non-catalog price or product
- Add a non-catalog item to your catalog
- Build request
- Send request
- Events
- Related pages