A reference guide for building AI agents: every method, how to authenticate, and the permissions each one needs.
The Paddle API is how an app or AI agent runs billing in a Paddle account: creating products and prices, charging a customer through a transaction, managing recurring subscriptions, and refunding a charge as an adjustment. Access is granted through an API key, and a key carries per-entity permissions that set which entities a call can read or write. A state change emits a notification that Paddle delivers to a registered destination, so an integration learns about activity without polling.
How an app or AI agent connects to Paddle determines what it can reach. There is a route for making calls, a route for receiving events, and a hosted server that exposes Paddle operations to agents, and each is governed by the key or secret behind it and the permissions that key carries.
The REST API takes JSON request bodies, returns JSON wrapped in a data envelope with a meta block, and pages through lists with a cursor, at https://api.paddle.com for live and https://sandbox-api.paddle.com for sandbox. A call authenticates with an API key sent as a Bearer token. The version is set with the Paddle-Version header.
Paddle POSTs a notification to an HTTPS destination registered for chosen events. The receiver verifies the Paddle-Signature header against the destination's secret key to confirm the request came from Paddle. Up to 10 destinations can be active, and delivered notifications can be listed, inspected, and replayed through the API.
Paddle publishes a hosted Model Context Protocol server at https://mcp.paddle.com that gives AI agents and MCP clients access to Paddle operations, with near parity to the Paddle Billing API across products, prices, customers, transactions, and subscriptions, plus up-to-date documentation. It works with Paddle Billing, not Paddle Classic.
A server-side API key authenticates first-party calls, sent as a Bearer token in the Authorization header. Keys created from May 2025 carry per-entity Read and Write permissions chosen when the key is made, so a key reaches only the entities it was scoped to. A key is shown once at creation; if it is lost it must be revoked and replaced. Each key belongs to one environment, live or sandbox.
A client-side token is safe to embed in front-end code. It is limited to client-safe operations, like opening a checkout and previewing prices, and cannot read or change billing data. It is created and managed separately from the secret API key.
The Paddle API is split into entities an agent can act on, like products, prices, customers, transactions, subscriptions, and adjustments. Each entity has its own methods, and a write in some of them charges a customer, cancels billing, or moves money back as a refund.
Methods for working with the products being sold.
Methods for working with the prices attached to products.
Methods for working with the people and businesses being billed.
Methods for working with transactions, the record of a charge.
Methods for working with recurring subscriptions.
Methods for refunds, credits, and chargebacks against billed transactions.
Methods for working with discount codes and amounts.
Methods for managing event destinations and inspecting delivered notifications.
Filter by method, access, or permission, or search any path. Select a row for version detail, rate limits, the related webhook event, and the source.
| Method | Endpoint | What it does | Access | Permission | Version | |
|---|---|---|---|---|---|---|
ProductsMethods for working with the products being sold.4 | ||||||
| POST | /products | Create a product, a good or service being sold. | write | product.write | Current | |
Write permission automatically includes read. Acts onproduct Permission (capability) product.writeVersionAvailable since the API’s base version Webhook event product.createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /products | List products, paginated, with optional filters. | read | product.read | Current | |
Read-only. Acts onproduct Permission (capability) product.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /products/{product_id} | Get a product using its ID. | read | product.read | Current | |
Read-only. Acts onproduct Permission (capability) product.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /products/{product_id} | Update a product, including archiving it (there is no delete). | write | product.write | Current | |
Set status to archived to retire a product; there is no delete operation. Acts onproduct Permission (capability) product.writeVersionAvailable since the API’s base version Webhook event product.updatedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
PricesMethods for working with the prices attached to products.3 | ||||||
| POST | /prices | Create a price defining how much and how often to charge for a product. | write | price.write | Current | |
A product can have many prices, like a monthly and an annual price. Acts onprice Permission (capability) price.writeVersionAvailable since the API’s base version Webhook event price.createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /prices | List prices, paginated, with optional filters. | read | price.read | Current | |
Read-only. Acts onprice Permission (capability) price.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /prices/{price_id} | Update a price, including archiving it. | write | price.write | Current | |
Set status to archived to retire a price. Acts onprice Permission (capability) price.writeVersionAvailable since the API’s base version Webhook event price.updatedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
CustomersMethods for working with the people and businesses being billed.4 | ||||||
| POST | /customers | Create a customer, a person or business being billed. | write | customer.write | Current | |
Paddle also creates customers automatically at checkout. Acts oncustomer Permission (capability) customer.writeVersionAvailable since the API’s base version Webhook event customer.createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /customers | List customers, paginated, with optional filters. | read | customer.read | Current | |
Read-only. Acts oncustomer Permission (capability) customer.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /customers/{customer_id} | Get a customer using its ID. | read | customer.read | Current | |
Read-only. Acts oncustomer Permission (capability) customer.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /customers/{customer_id} | Update a customer, including archiving it. | write | customer.write | Current | |
Set status to archived to retire a customer. Acts oncustomer Permission (capability) customer.writeVersionAvailable since the API’s base version Webhook event customer.updatedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
TransactionsMethods for working with transactions, the record of a charge.4 | ||||||
| POST | /transactions | Create a transaction to bill or invoice a customer for items. | write | transaction.write | Current | |
Can collect payment automatically or be issued as an invoice for manual payment. Acts ontransaction Permission (capability) transaction.writeVersionAvailable since the API’s base version Webhook event transaction.createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /transactions | List transactions, paginated, with optional filters. | read | transaction.read | Current | |
Read-only. Acts ontransaction Permission (capability) transaction.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /transactions/{transaction_id} | Get a transaction using its ID. | read | transaction.read | Current | |
Read-only; use the include parameter to pull in related entities. Acts ontransaction Permission (capability) transaction.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /transactions/{transaction_id}/invoice | Get a link to a PDF invoice for a billed or completed transaction. | read | transaction.read | Current | |
Read-only; returns a temporary URL to the PDF. Acts ontransaction Permission (capability) transaction.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
SubscriptionsMethods for working with recurring subscriptions.7 | ||||||
| GET | /subscriptions | List subscriptions, paginated, with optional filters. | read | subscription.read | Current | |
Read-only. Acts onsubscription Permission (capability) subscription.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /subscriptions/{subscription_id} | Get a subscription using its ID. | read | subscription.read | Current | |
Read-only. Acts onsubscription Permission (capability) subscription.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /subscriptions/{subscription_id} | Update a subscription, like changing items, quantity, or proration. | write | subscription.write | Current | |
An update that charges immediately counts against the per-subscription charge limit. Acts onsubscription Permission (capability) subscription.writeVersionAvailable since the API’s base version Webhook event subscription.updatedRate limit20 chargeable updates per hour, 100 per 24 hours, per subscription SourceOfficial documentation ↗ | ||||||
| POST | /subscriptions/{subscription_id}/cancel | Cancel a subscription, immediately or at the end of the billing period. | write | subscription.write | Current | |
Ends recurring billing; cannot be undone once a subscription is canceled. Acts onsubscription Permission (capability) subscription.writeVersionAvailable since the API’s base version Webhook event subscription.canceledRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /subscriptions/{subscription_id}/pause | Pause a subscription so billing stops until it is resumed. | write | subscription.write | Current | |
Pauses at the end of the billing period by default. Acts onsubscription Permission (capability) subscription.writeVersionAvailable since the API’s base version Webhook event subscription.pausedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /subscriptions/{subscription_id}/resume | Resume a paused or scheduled-to-pause subscription. | write | subscription.write | Current | |
Restarts recurring billing from the chosen date. Acts onsubscription Permission (capability) subscription.writeVersionAvailable since the API’s base version Webhook event subscription.resumedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /subscriptions/{subscription_id}/charge | Create a one-time charge for items on top of an existing subscription. | write | subscription.write | Current | |
An immediate charge counts against the per-subscription charge limit. Acts onsubscription Permission (capability) subscription.writeVersionAvailable since the API’s base version Webhook eventNone Rate limit20 chargeable updates per hour, 100 per 24 hours, per subscription SourceOfficial documentation ↗ | ||||||
Adjustments (refunds & credits)Methods for refunds, credits, and chargebacks against billed transactions.3 | ||||||
| POST | /adjustments | Create an adjustment to refund, credit, or charge back a billed transaction. | write | adjustment.write | Current | |
A full or partial refund returns money to the customer; a refund needs Paddle approval before it is paid out. Acts onadjustment Permission (capability) adjustment.writeVersionAvailable since the API’s base version Webhook event adjustment.createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /adjustments | List adjustments, paginated, with optional filters. | read | adjustment.read | Current | |
Read-only. Acts onadjustment Permission (capability) adjustment.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /adjustments/{adjustment_id}/credit-note | Get a link to a PDF credit note for an adjustment. | read | adjustment.read | Current | |
Read-only; returns a temporary URL to the PDF. Acts onadjustment Permission (capability) adjustment.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
DiscountsMethods for working with discount codes and amounts.3 | ||||||
| POST | /discounts | Create a discount, a percentage or flat amount off, with an optional code. | write | discount.write | Current | |
Can be limited by usage count, dates, or specific products and prices. Acts ondiscount Permission (capability) discount.writeVersionAvailable since the API’s base version Webhook event discount.createdRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /discounts | List discounts, paginated, with optional filters. | read | discount.read | Current | |
Read-only. Acts ondiscount Permission (capability) discount.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| PATCH | /discounts/{discount_id} | Update a discount, including archiving it. | write | discount.write | Current | |
Set status to archived to retire a discount. Acts ondiscount Permission (capability) discount.writeVersionAvailable since the API’s base version Webhook event discount.updatedRate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Notifications & WebhooksMethods for managing event destinations and inspecting delivered notifications.4 | ||||||
| POST | /notification-settings | Create a notification destination, choosing which events go where. | write | notification_setting.write | Current | |
A maximum of 10 destinations can be active at once. Acts onnotification_setting Permission (capability) notification_setting.writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /notification-settings | List notification destinations. | read | notification_setting.read | Current | |
Read-only. Acts onnotification_setting Permission (capability) notification_setting.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| GET | /notifications | List notifications that Paddle has tried to deliver. | read | notification.read | Current | |
Read-only. Acts onnotification Permission (capability) notification.readVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
| POST | /notifications/{notification_id}/replay | Replay a notification to its destination, for example after a delivery failure. | write | notification.write | Current | |
Resends the same event so a receiver can reprocess it. Acts onnotification Permission (capability) notification.writeVersionAvailable since the API’s base version Webhook eventNone Rate limitStandard limits apply SourceOfficial documentation ↗ | ||||||
Paddle can notify an app when something happens in an account, like a transaction completing or a subscription being canceled. It POSTs a notification describing what changed to a destination that has been registered for that event, so an integration learns about activity without polling.
| Event | What it signals | Triggered by |
|---|---|---|
transaction.created | A new transaction was created, the record of a charge against a customer. | /transactions |
transaction.completed | A transaction has been fully processed and will not change further. An integration provisions access on this event. | /transactions |
subscription.updated | A subscription changed, like an item, quantity, status, or schedule change. | /subscriptions/{subscription_id} |
subscription.canceled | A subscription was canceled and recurring billing has ended. An integration revokes access on this event. | /subscriptions/{subscription_id}/cancel |
subscription.paused | A subscription was paused, so billing stops until it is resumed. | /subscriptions/{subscription_id}/pause |
subscription.resumed | A paused subscription was resumed and recurring billing has restarted. | /subscriptions/{subscription_id}/resume |
adjustment.created | An adjustment was created, like a refund, credit, or chargeback against a transaction. | /adjustments |
customer.created | A new customer was created, by the API or at checkout. | /customers |
customer.updated | A customer's details changed. | /customers/{customer_id} |
product.created | A new product was created. | /products |
product.updated | A product's details changed, including being archived. | /products/{product_id} |
price.created | A new price was created for a product. | /prices |
price.updated | A price's details changed, including being archived. | /prices/{price_id} |
discount.created | A new discount was created. | /discounts |
discount.updated | A discount's details changed, including being archived. | /discounts/{discount_id} |
Paddle limits how fast an app can call, measured as a number of requests per minute per IP address, with a higher allowance for the preview endpoints that price checkout pages.
Paddle meters requests by rate per IP address, not by a per-method cost. Most operations allow 240 requests per minute per IP; the preview transaction and preview prices endpoints allow 1,000 per minute because they price checkout pages. Going over returns HTTP 429 with a Retry-After header, and that IP cannot make another request for 60 seconds. Separately, an immediate charge on a subscription is capped per subscription, at 20 chargeable updates per hour and 100 per 24 hours, shown on those rows.
A list endpoint is cursor-based. The per parameter sets the page size, and the response meta block carries pagination details including a has_more flag and a next link that already contains the cursor (the after parameter) for the following page. Results can be ordered and filtered with query parameters, and the SDKs offer auto-pagination.
A list endpoint returns a bounded number of records per page, set by the per parameter. Request bodies and headers have size ceilings that return 413 (request_body_too_large) or 414 (request_headers_too_large) when exceeded. Up to 10 notification destinations can be active at once.
The status codes an agent should handle, and what to do about each.
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | bad_request / invalid_field | The request was malformed or a field failed validation. A validation error returns an errors array naming each invalid field. | Read the detail and the errors array, fix the request, and resend. The request is not retryable as-is. |
| 401 | authentication_missing / invalid_token | No API key was sent, the Authorization header was malformed, or the key is invalid. | Send a valid API key as a Bearer token in the Authorization header for the right environment, and rotate the key if it is compromised. |
| 403 | forbidden | The key is valid but lacks the entity permission the request needs, for example a write call with a read-only key. | Grant the entity permission on the API key, or use a key that carries it. |
| 404 | not_found | The requested entity does not exist, or is not visible to this key, account, or environment. | Verify the entity ID and confirm it lives in the same environment and account. |
| 409 | conflict | The request conflicts with the current state of the entity, like an action that the entity's status does not allow. | Re-read the entity, confirm it is in a valid state for the action, and retry. |
| 429 | too_many_requests | The IP address exceeded the rate limit. A Retry-After header gives the seconds to wait, and that IP cannot make another request for 60 seconds. | Back off until the Retry-After window passes, then retry with exponential backoff and smooth the request rate. |
| 500 | internal_error | An error on Paddle's side, which can also appear as 502 or 503. It is rare. | Retry with backoff, and include the meta.request_id when contacting Paddle support if it persists. |
Paddle versions its API with a single sequential number and only mints a new version for a breaking change, so older versions keep working until an integration chooses to move up.
Paddle Billing uses a single sequential API version, currently 1, set per request with the Paddle-Version header and defaulting per account. Only a breaking change mints a new version, and older versions keep working. The entries below are dated feature releases shipped within version 1, drawn from the developer changelog.
Paddle moved its Model Context Protocol server to a hosted remote service, giving AI agents access to the full Paddle API alongside up-to-date documentation.
Paddle introduced a new API key format that carries per-entity Read and Write permissions and supports secret scanning. Keys created before this date are 50-character strings without permissions.
Paddle Billing, the entity-oriented REST API with products, prices, customers, transactions, subscriptions, adjustments, and notifications, became generally available as the successor to Paddle Classic.
Pin a version with the Paddle-Version header and move up only when ready.
Paddle developer changelog ↗Bollard AI sits between a team's AI agents and Paddle. Grant each agent exactly the access it needs, read or write, entity by entity, and every call is checked and logged.