Create a transaction
Transactions are the central billing entity in Paddle. Create a transaction to collect using checkout or invoice. Paddle automatically creates transactions for subscription lifecycle events.
To bill a customer, you need a transaction. It holds all the information about a charge you're billing for, including customer details, items, calculated tax and localized pricing, and payments.
Paddle automatically creates transactions for subscription lifecycle events and when checkouts are opened, but you can create your own transactions using the API or Paddle dashboard.
How it works
Transactions are at the heart of Paddle. They tie together products, prices, and discounts with customers to calculate and capture revenue for checkouts, invoices, and subscriptions.
All revenue in Paddle is calculated and captured using transactions. Paddle creates transactions automatically for subscription lifecycle events and when checkouts are opened, and you may also create your own transactions using the API or Paddle dashboard.
Transaction lifecycle
Transactions are initially created as draft
or ready
, depending on the information supplied. As you work with a transaction entity, they move to completed
:
Draft
draft
transactions are missing required fields for billing. Checkouts opened by Paddle.js with only items createdraft
transactions, since they're missing customer and address information initially.Ready
Transactions are
ready
when they have all the required fields for billing. When Paddle Checkout captures customer name, country and (in some regions) ZIP or postal code, then transactions move toready
.Billed
You may optionally mark a transaction as
billed
. At this point, it's considered a financial record and can't be changed. This is typically used as part of an invoicing workflow to issue an invoice, or to prevent a customer from changing items or quantities at checkout.Paid
When Paddle collects payment successfully, transactions are automatically
paid
. This is an interim status while completed transaction processing happens. Paddle updates the transaction with information about fees, earnings, and totals for payouts. It also adds the relatedsubscription_id
andinvoice_number
for automatically-collected transactions.Completed transaction processing usually takes less than a second, so you won't typically encounter transactions that are
paid
when working with the API.Completed
After all transaction processing is completed, transactions are automatically
completed
.
Paddle automatically sets transactions as draft
, ready
, paid
, and completed
. You can set transactions as billed
or canceled
using the API.
This guide focuses on creating automatically-collected transactions. You can also create manually-collected transactions, meaning Paddle sends an invoice document that must be paid manually.
Before you begin
Set your default payment link
Before creating a transaction, you'll need to:
- 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.
Create customers
If you're working with the Paddle dashboard, you can create all the entities that you'll be working with as you create your transaction.
If you're working with the API, you'll need to:
- Optionally create a related business
Create products and prices — optional
Transactions work with products and prices to say what you're billing for. You can bill for items from your catalog, or non-catalog items for one-off or bespoke items.
To bill for an item in your catalog, create a product and a related price.
Create a draft or ready transaction
Draft transactions contain an items
list, but don't include address or customer details which are required for billing. Ready transactions contain an items
list and all required fields for billing, including address and customer details.
You may pass a draft or ready transaction to a checkout to capture customer or address information, and collect for payment.
Create a draft or transaction using the API in three steps:
Build a request that includes a list of items that you'd like to bill for, and information about who you're billing.
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 either:
An item from your catalog
Include a price ID and quantity for each item.
A non-catalog item
Include a price object and quantity for each item.
Non-catalog items are one-off or bespoke items that are specific to that transaction. See: Bill for non-catalog items
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.
List of items to charge for.
Quantity of this item on the transaction.
Paddle ID of an existing catalog price to add to this transaction, prefixed with pri_
.
List of items to charge for.
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.
Internal description for this price, not shown to customers. Typically notes for your team.
Name of this price, shown to customers at checkout and on invoices. Typically describes how often the related product bills.
How often this price should be charged. null
if price is non-recurring (one-time).
Trial period for the product related to this price. The billing cycle begins once the trial period is over. null
for no trial period. Requires billing_cycle
.
How tax is calculated for this price.
Base price. This price applies to all customers, except for customers located in countries where you have unit_price_overrides
.
List of unit price overrides. Use to override the base price with a custom price and currency for a country or group of countries.
Limits on how many times the related product can be purchased at this price. Useful for discount campaigns. If omitted, defaults to 1-100.
Your own structured key-value data.
Paddle ID for the product that this price is for, prefixed with pro_
.
Quantity of this item on the transaction.
Include customer_id
and address_id
to say who this invoice is for.
If you're working with a business, include business_id
too.
Transactions are automatically marked as ready
when they have customer_id
, address_id
, and items
. This means that they're ready to be issued (marked as billed
).
Paddle ID of the customer that this invoice is for, prefixed with ctm_
.
Paddle ID of the address that this invoice is for, prefixed with add_
.
Paddle ID of the business that this invoice is for, prefixed with biz_
.
Request
123456781{
2 "items": [
3 {
4 "quantity": 10,
5 "price_id": "pri_01gsz8x8sawmvhz1pv30nge1ke"
6 }
7 ]
8}
Request
123456789101{
2 "items": [
3 {
4 "quantity": 10,
5 "price_id": "pri_01gsz8x8sawmvhz1pv30nge1ke"
6 }
7 ],
8 "customer_id": "ctm_01h8441jn5pcwrfhwh78jqt8hk",
9 "address_id": "add_01h848pep46enq8y372x7maj0p"
10}
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.
There are no calculated taxes, since Paddle doesn't have address information.
12345678910111213141516171819201{
2 "data": {
3 "customer_id": null,
4 "address_id": null,
5 "business_id": null,
6 "subscription_id": null,
7 "currency_code": "USD",
8 "address": null,
9 "customer_ip_address": null,
10 "discount_id": null,
11 "items": [
12 {
13 "price": {
14 "id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
15 "description": "Monthly (per seat)",
16 "name": "Monthly (per seat)",
17 "product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
18 "billing_cycle": {
19 "interval": "month",
20 "frequency": 1
Response
If successful, Paddle returns a preview of the new transaction entity.
12345678910111213141516171819201{
2 "data": {
3 "customer_id": "ctm_01h8441jn5pcwrfhwh78jqt8hk",
4 "address_id": "add_01h848pep46enq8y372x7maj0p",
5 "business_id": null,
6 "subscription_id": null,
7 "currency_code": "USD",
8 "address": {
9 "postal_code": "10021",
10 "country_code": "US"
11 },
12 "customer_ip_address": null,
13 "discount_id": null,
14 "items": [
15 {
16 "price": {
17 "id": "pri_01gsz8x8sawmvhz1pv30nge1ke",
18 "description": "Monthly (per seat)",
19 "name": "Monthly (per seat)",
20 "product_id": "pro_01gsz4t5hdjse780zja8vvr7jg",
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 with the status of draft
.
The new transaction has collection_mode
as automatic
, which means Paddle collects automatically using a saved payment method. If no payment method is saved, you can pass this transaction to Paddle.js to open a checkout for it.
There are no calculated taxes, since Paddle doesn't have address information.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01hgk4aer7mejqsgzs8bgvp1ke",
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-01T16:45:20.594624214Z",
19 "updated_at": "2023-12-01T16:45:20.594624214Z",
20 "billed_at": null,
Response
If successful, Paddle responds with a copy of the new transaction entity with the status of ready
.
The new transaction has collection_mode
as automatic
, which means Paddle collects automatically using a saved payment method. If no payment method is saved, you can pass this transaction to Paddle.js to open a checkout for it.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01hgk505qdyvbrmhpp14b97jgz",
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": "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-01T16:57:12.591685111Z",
19 "updated_at": "2023-12-01T16:57:12.591685111Z",
20 "billed_at": null,
Update a transaction
While your transaction is draft
or ready
, you can make changes to it and the items on it. You can work with items, apply a discount, change customer information, or add or remove custom data.
If you're working with a draft
transaction, Paddle automatically marks it as ready
when you add customer_id
and address_id
.
Transactions are financial records. You can't edit them if they're billed, canceled, or completed. Cancel a transaction and create another or create an adjustment if you need to make changes to a billed or completed transaction.
Update a transaction using the API in two steps:
Build a request that includes a list of items that you'd like to bill for, and information about who you're billing. If you're adding new items, your request should include any existing items that you'd like to keep.
Send the request to update your transaction. Paddle updates it.
Build request
Build a request with any data that you'd like to change. You can change any writeable fields at this point, including address, customer, and items.
When working with items
, you should send the complete list of items that you'd like to be against your invoice — including any existing items. If you omit an item, it's removed from the items list. See: Work with lists
Request
This example adds a discount to a transaction. Apply a discount by including discount_id
in your request.
1231{
2 "discount_id": "dsc_01gy7qp5pqhnyd22yspwane77h"
3}
Send request
Send a PATCH
request to the /transactions/{transaction_id}
endpoint.
Paddle ID of the transaction entity to work with.
Response
If successful, Paddle responds with a copy of the updated transaction entity.
12345678910111213141516171819201{
2 "data": {
3 "id": "txn_01gzkcdstcwq4cj8waj812v9my",
4 "status": "ready",
5 "customer_id": "ctm_01gzgmxdmgkgc7p94b5kgqq82p",
6 "address_id": "add_01gzkce0amtjsqv8xxd1rv3dna",
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": "GBP",
17 "discount_id": "dsc_01gy7qp5pqhnyd22yspwane77h",
18 "created_at": "2023-05-04T12:40:07.834144Z",
19 "updated_at": "2023-05-18T13:59:56.611406607Z",
20 "billed_at": null,
Mark a transaction as billed
You can mark a transaction as billed
using the API to say it's finalized, meaning it's considered a financial record and cannot be changed.
This is typically used for manually-collected transactions (invoices), as part of an invoicing workflow. Marking a transaction as billed is essentially issuing an invoice. It gets an invoice number and is sent to the customer.
You don't need to mark an automatically-collected transaction as billed
, and it's not typically part of a self-service workflow. However, you may like to do this if you plan to create a checkout for this transaction to prevent a customer from changing items or quantities at checkout.
See: Issue an invoice
You can create a transaction and mark it as
billed
by including"status": "billed"
in your initial request, along with the other required fields — no need to make a separate request.
Pass a transaction to a checkout
Automatically-collected transactions include checkout.url
, which you can send to customers to open a checkout to capture customer information and collect payment for this transaction.
You can also pass a transaction to a checkout using Paddle.js to collect for it.
Events
transaction.created | Occurs when a transaction is created initially. |
transaction.updated | Occurs when a transaction is updated. |
transaction.ready | Occurs when a transaction is ready to be billed. It has all of the required fields for billing. |
transaction.billed | Occurs when a transaction is marked as billed. |