Paddle
Verified on 25 October 2026 against the Paddle Billing API, version 1 (sandbox).
Paddle is a merchant of record: it sells your product on your behalf and handles sales tax, payment processing and compliance. The connector pins your gateway to https://api.paddle.com and seals your API key there, so an agent can answer questions about your revenue (who is subscribed, what a customer has been billed, which transactions failed) without holding a credential that could bill or refund anyone. The three capabilities that do move money are approval-gated and start switched off.
What you need
A Paddle API key.
- Sign in to Paddle and go to Developer Tools → Authentication.
- Select the API keys tab, then New API key.
- Name it something you will recognize later, such as
permaura. - Choose the permissions. For read-only use, tick
product.read,price.read,customer.read,subscription.readandtransaction.read. Addtransaction.write,adjustment.writeandsubscription.writeonly if you intend to enable the three write capabilities below. - Set an expiry (Paddle defaults to 90 days, maximum one year) and save. Copy the key straight away: it starts
pdl_live_apikey_and Paddle shows it only once. Lose it and you have to revoke and reissue.
Paddle's write permissions imply the matching read permission, so a key with transaction.write can also read transactions. Grant the narrowest set that covers what you plan to switch on.
Add the connection
In the console, open Access → Connections → Add connection, pick Paddle from the catalog, and paste the API key when prompted. It is sealed on your gateway at that moment and is never displayed again. You can rotate or replace it, but not read it back.
The nine read capabilities arrive switched on; the three writes arrive switched off. Nothing is usable until a grant allows it.
What the agent can do
| Action | What it does | On by default |
|---|---|---|
products.list | Lists products, filterable by status and type | Yes |
products.read | Retrieves one product by id | Yes |
prices.list | Lists prices, filterable by id, product_id, status and recurring | Yes |
customers.list | Lists customers, filterable by email, search and status | Yes |
customers.read | Retrieves one customer by id | Yes |
subscriptions.list | Lists subscriptions, filterable by customer_id, price_id and status | Yes |
subscriptions.read | Retrieves one subscription by id | Yes |
transactions.list | Lists transactions, filterable by customer_id, subscription_id, status and billed_at | Yes |
transactions.read | Retrieves one transaction by id | Yes |
transactions.create | Creates a billable transaction against a customer | No, approval-gated |
adjustments.create | Refunds or credits a transaction | No, approval-gated |
subscriptions.cancel | Cancels a subscription | No, approval-gated |
The three writes are marked critical and require a human approval for every call, even after you switch them on. That is deliberate: each one either bills a customer, gives money back, or ends a paying relationship. That approval can come from the console, the Permaura app or the CLI; to make it wait for a signature from your paired device, set the action to Device-signed in its policy or raise the approval floor.
transactions.create does not capture a payment on the spot, but it is not harmless either. With collection_mode of manual and status of billed, Paddle sends your customer a real invoice with payment terms. With collection_mode of automatic it returns a checkout.url for them to pay through, and once that payment completes Paddle creates a subscription for any recurring items on the transaction. Read items, customer_id, collection_mode and status before you approve one.
adjustments.create covers both refunds and credits: the action field in the request body chooses between refund and credit, and Paddle requires a transaction_id and a reason with either.
subscriptions.cancel takes an effective_from of next_billing_period (the default, which schedules the cancellation for the end of the current period) or immediately. Check which one the request is asking for before you approve it; they are very different outcomes for the customer.
Good to know
- Sandbox is a different host. This connector is pinned to production,
https://api.paddle.com. Paddle's sandbox lives athttps://sandbox-api.paddle.comwith its own separate API keys. A pinned base URL is the SSRF guard (an agent can never reach any other host through this connection) andPOST /v1/connections/from-presetgives you no way to override it. To test against sandbox, install a second copy of the manifest under its own id: takepaddle.json, change"id"to something likepaddle-sandbox, changebase_urltohttps://sandbox-api.paddle.com,POSTit to/v1/connectors/install, and create the connection from that. - The API version is pinned to
Paddle-Version: 1. Paddle treats the header as optional and falls back to your account's default version, but pinning it means a change to your account default cannot silently alter what your agent gets back. Version 1 is the only version Paddle has published. - A refund is submitted, not done. Paddle itself reviews most refunds on live accounts, so a successful
adjustments.createwithaction: refundcomes back aspending_approvaland later becomesapprovedorrejected. Watch theadjustment.updatedwebhook rather than assuming the money has moved. Credits need no Paddle review and are created asapproved. On sandbox, refunds are auto-approved every ten minutes. - Customer data is redacted.
email,first_line,second_line,city,postal_code,cardholder_name,last4,expiry_month,expiry_yearandcustomer_ip_addressare stripped from responses before the agent sees them. An agent can tell you a customer's subscription is past due; it cannot read their address or card details. - There is no
prices.read. Fetching prices by id is covered byprices.listwith theidfilter, which takes a comma-separated list of price ids: one capability instead of two. - Paging uses
after, not page numbers. Every list capability acceptsper_page(default 50, maximum 200) andafter, which takes the id of the last item you saw. Paddle returns the next cursor inmeta.pagination. - API keys expire. If you set the default 90-day expiry, the connection will start failing on that date. Rotate the key in Paddle and paste the new one into the connection before then, or set a longer expiry when you create it.
- The kill switch is instant. Disabling the connection in the console refuses every call through it immediately, across every agent and grant, without unpicking individual permissions.