What's new?
We updated the Paddle platform so that now you can create transactions for products and prices that aren't in your catalog.
When creating or updating a transaction, you can now pass price and product attributes directly to a transaction, as well as passing existing price IDs.
In future updates, we'll release functionality to let you bill one-time non-catalog items to a subscription, then work with recurring non-catalog items on a subscription. These changes are scheduled for Q1 2024.
How it works
As well as creating transactions for items in your product catalog, you can create transactions for non-catalog items by passing a price and (optionally) a product object directly to a transaction when creating or updating.
Adding non-catalog items to a transaction is great for one-off or bespoke items that are specific to that transaction. They let you manage your product catalog outside of Paddle. When adding a custom item to a transaction, you can:
- Pass a price object for an existing product to charge for a custom price for a catalog product
- Pass a price object and a product object to charge for a custom price for a custom product
This means you have the flexibility to manage your catalog in the way that best suits the way that you work. For example:
- If you work with third-party app stores, you can manage your product catalog centrally and pass custom prices and products to transactions.
- When invoicing enterprise customers, you can agree custom prices for existing products when negotiating.
- You can use Paddle to bill for large product catalogs where prices may change daily, like eBook resellers or customers who may show personalized prices to different users.
Examples
Create a transaction for a one-time item
This example creates a draft transaction for a one-time non-catalog item. It's for a custom product.
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.
/transactions { "items": [ { "quantity": 1, "price": { "description": "New user price (FTUE)", "name": "Welcome price", "unit_price": { "amount": "999", "currency_code": "USD" }, "product": { "name": "Invigaron Berries Hoard", "tax_category": "standard", "description": "Start the game with 20 extra seconds play time!" } } } ], "currency_code": "USD"}{ "data": { "id": "txn_01hj3s8yt41c6kaqm8rx9zfgtf", "status": "draft", "customer_id": null, "address_id": null, "business_id": null, "custom_data": null, "origin": "api", "collection_mode": "automatic", "subscription_id": null, "invoice_id": null, "invoice_number": null, "billing_details": null, "billing_period": null, "currency_code": "USD", "discount_id": null, "created_at": "2023-12-20T14:15:04.47996325Z", "updated_at": "2023-12-20T14:15:04.47996325Z", "billed_at": null, "items": [ { "price": { "id": "pri_01hj3s8yyfhtfvv9z9amcp6m55", "description": "New user price (FTUE)", "type": "custom", "name": "Welcome price", "product_id": "pro_01hj3s8yw3rpmp1y1n1sy8ty2x", "billing_cycle": null, "trial_period": null, "tax_mode": "account_setting", "unit_price": { "amount": "999", "currency_code": "USD" }, "unit_price_overrides": [], "custom_data": null, "quantity": { "minimum": 1, "maximum": 100 }, "status": "active" }, "quantity": 1 } ], "details": { "tax_rates_used": [ { "tax_rate": "0", "totals": { "subtotal": "999", "discount": "0", "tax": "0", "total": "999" } } ], "totals": { "subtotal": "999", "tax": "0", "discount": "0", "total": "999", "grand_total": "999", "fee": null, "credit": "0", "credit_to_balance": "0", "balance": "999", "earnings": null, "currency_code": "USD" }, "adjusted_totals": { "subtotal": "999", "tax": "0", "total": "999", "grand_total": "999", "fee": "0", "earnings": "0", "currency_code": "USD" }, "payout_totals": null, "adjusted_payout_totals": null, "line_items": [ { "id": "txnitm_01hj3s8z0gswx71j2agzgp42zz", "price_id": "pri_01hj3s8yyfhtfvv9z9amcp6m55", "quantity": 1, "totals": { "subtotal": "999", "tax": "0", "discount": "0", "total": "999" }, "product": { "id": "pro_01hj3s8yw3rpmp1y1n1sy8ty2x", "name": "Invigaron Berries Hoard", "description": "Start the game with 20 extra seconds play time!", "type": "custom", "tax_category": "standard", "image_url": null, "custom_data": null, "status": "active" }, "tax_rate": "0", "unit_totals": { "subtotal": "999", "tax": "0", "discount": "0", "total": "999" } } ] }, "payments": [], "checkout": { "url": "https://aeroedit.com/pay?_ptxn=txn_01hj3s8yt41c6kaqm8rx9zfgtf" } }, "meta": { "request_id": "0ebcb490-0a6e-42ad-9d1d-b35d5a772030" }}Create a transaction for a recurring item
This example creates a draft invoice for a 50-user enterprise plan. It's for an existing product, related using the product_id field.
Collection mode is manual, meaning this transaction is an invoice. Once issued, Paddle sends an invoice that must be paid manually.
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.
/transactions { "items": [ { "quantity": 50, "price": { "product_id": "pro_01gsz4vmqbjk3x4vvtafffd540", "description": "Globex annual 2024", "name": "Annual (per seat) deal for Globex", "billing_cycle": { "interval": "year", "frequency": 1 }, "unit_price": { "amount": "50000", "currency_code": "USD" } } } ], "customer_id": "ctm_01h8441jn5pcwrfhwh78jqt8hk", "address_id": "add_01h848pep46enq8y372x7maj0p", "currency_code": "USD", "collection_mode": "manual", "billing_details": { "enable_checkout": false, "purchase_order_number": "PO-2400", "payment_terms": { "interval": "day", "frequency": 14 }, "additional_information": "Price agreed with Sam. Looking forward to working together in the year ahead!" }, "billing_period": { "starts_at": "2024-04-01T00:00:00Z", "ends_at": "2025-03-31T23:59:00Z" }}{ "data": { "id": "txn_01hj3ryktw234aj7s0wt5sp69g", "status": "ready", "customer_id": "ctm_01h8441jn5pcwrfhwh78jqt8hk", "address_id": "add_01h848pep46enq8y372x7maj0p", "business_id": null, "custom_data": null, "origin": "api", "collection_mode": "manual", "subscription_id": null, "invoice_id": null, "invoice_number": null, "billing_details": { "enable_checkout": false, "payment_terms": { "interval": "day", "frequency": 14 }, "purchase_order_number": "PO-2400", "additional_information": "Price agreed with Sam. Looking forward to working together in the year ahead!" }, "billing_period": null, "currency_code": "USD", "discount_id": null, "created_at": "2023-12-20T14:09:25.78998194Z", "updated_at": "2023-12-20T14:09:25.78998194Z", "billed_at": null, "items": [ { "price": { "id": "pri_01hj3rykvg0r83rnpwp5h87wy8", "description": "Globex annual 2024", "type": "custom", "name": "Annual (per seat) renewal deal for Globex", "product_id": "pro_01gsz4vmqbjk3x4vvtafffd540", "billing_cycle": { "interval": "year", "frequency": 1 }, "trial_period": null, "tax_mode": "account_setting", "unit_price": { "amount": "50000", "currency_code": "USD" }, "unit_price_overrides": [], "custom_data": null, "quantity": { "minimum": 1, "maximum": 100 }, "status": "active" }, "quantity": 50 } ], "details": { "tax_rates_used": [ { "tax_rate": "0.08875", "totals": { "subtotal": "2500000", "discount": "0", "tax": "221875", "total": "2721875" } } ], "totals": { "subtotal": "2500000", "tax": "221875", "discount": "0", "total": "2721875", "grand_total": "2721875", "fee": null, "credit": "0", "credit_to_balance": "0", "balance": "2721875", "earnings": null, "currency_code": "USD" }, "adjusted_totals": { "subtotal": "2500000", "tax": "221875", "total": "2721875", "grand_total": "2721875", "fee": "0", "earnings": "0", "currency_code": "USD" }, "payout_totals": null, "adjusted_payout_totals": null, "line_items": [ { "id": "txnitm_01hj3rym8ff2yrkv43vstzfrx5", "price_id": "pri_01hj3rykvg0r83rnpwp5h87wy8", "quantity": 50, "totals": { "subtotal": "2500000", "tax": "221875", "discount": "0", "total": "2721875" }, "product": { "id": "pro_01gsz4vmqbjk3x4vvtafffd540", "name": "ChatApp Enterprise", "description": "The ultimate solution for businesses that require top-of-the-line features and customizations. Includes all the features of the Pro plan, plus personalized onboarding, dedicated account management, and the ability to pay via invoice.", "type": "standard", "tax_category": "standard", "image_url": "https://paddle-sandbox.s3.amazonaws.com/user/10889/2nmP8MQSret0aWeDemRw_icon1.png", "custom_data": null, "status": "active" }, "tax_rate": "0.08875", "unit_totals": { "subtotal": "50000", "tax": "4437", "discount": "0", "total": "54437" } } ] }, "payments": [], "checkout": { "url": null } }, "meta": { "request_id": "ade613b5-d62e-4f0a-93cb-a64516598fee" }}Next steps
This change is available in version 1 of the Paddle API.
It's a non-breaking change, meaning it doesn't impact existing integrations. You can continue creating transactions by passing price IDs for items in your product catalog. We recommend this for customers who sell a set of digital products at the same price points.
You can create or update transactions using the API to start charging for non-catalog items.
This is part of a set of changes around non-catalog items. In future updates, we'll release functionality to let you bill one-time non-catalog items to a subscription, then work with recurring non-catalog items on a subscription. These changes are scheduled for Q1 2024.
Summary of changes
| Entity | Field | Change | Type |
|---|---|---|---|
| transaction | items[].price_id | ~ Updated | Field |
| This field is no longer required if you include a price object instead. | |||
| transaction | items[].price | + Added | Field |
| You can send a price object instead of a price_id to bill for a non-catalog item. | |||