Paddle
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 recognise 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 on your paired device 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.
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.