---
title: "Selling GitHub Repo Access with Paddle as Your Merchant of Record"
description: "The provider guide for the locked-out cohort: Paddle as Merchant of Record carrying tax and disputes, RepoAccess carrying delivery - selling paid repos from countries Stripe does not serve."
canonical: "https://edgekits.dev/en/blog/paddle-merchant-of-record-github-repo-access/"
published: "2026-09-05"
tags: ["Paddle", "Merchant of Record", "GitHub", "Payments", "Cloudflare Workers", "RepoAccess"]
---

[Stripe's list of supported countries](https://stripe.com/global) has 47 entries. The UN has 193 members. If you write code in one of the other 146 - where India is "Preview, contact sales", a few African countries route to a partner, and whole regions are simply not on the page - every "just connect Stripe" tutorial reads like a joke told at your expense. This article is the version without the joke: Paddle as your Merchant of Record, and a delivery layer you own.

## What Paddle as a Merchant of Record does for a code seller

A Merchant of Record resells your product to the buyer as its own. Paddle is the legal seller on the receipt: it charges the card, registers and remits the sales tax, and absorbs the disputes. You invoice one counterparty - Paddle - instead of a planet's worth of tax jurisdictions.

For a seller inside Stripe's list, that is a convenience. For everyone else it is the mechanism that makes selling possible at all: your buyers transact with Paddle, so the checkout does not depend on whether your country is in anyone's dropdown. I sell through Paddle from a country that is not on Stripe's list; this setup is not a thought experiment, it is my production stack. Paddle onboards sellers through a verification review of your business rather than a country list - check its current terms for your jurisdiction, and expect the review to be real.

> **TL;DR**
> - Paddle is the Merchant of Record: it is the legal seller, so tax registration, remittance and disputes are its problem
> - That turns geography from a wall into a checkbox - the checkout works whether or not Stripe serves your country
> - Paddle sells and charges; it does not deliver GitHub access - that half is yours, and this article wires it
> - Delivery runs as one Cloudflare Worker you own: webhook in, team invite out, refunds revoke automatically

## Paddle vs Stripe: the fork is jurisdiction, not features

Most Paddle-versus-Stripe comparisons argue about fees and APIs. For a code seller the real fork comes earlier, at the signup dropdown: one of these two will take you, and whether the other one will depends on where you live.

If Stripe serves your country, the comparison is a fair trade. Stripe's [standard card rate](https://stripe.com/pricing) starts around 2.9% plus 30 cents and leaves you as the seller of record: sales tax registration and remittance stay on your desk, jurisdiction by jurisdiction.

Paddle charges [5% plus 50 cents per checkout](https://www.paddle.com/pricing) - roughly the difference between a payment processor and a legal counterparty. The extra points buy the Merchant of Record: Paddle owes the tax man, Paddle answers the chargeback, and your accounting sees one invoice.

If Stripe does not serve your country, there is no trade to weigh. The alternatives mostly inherit Stripe's geography - Polar pays out through Stripe Connect, and Lemon Squeezy is folding into [Stripe Managed Payments](/en/blog/lemon-squeezy-stripe-managed-payments-repo-access/) - so the MoR that stands on its own rails is the door, and the fee is the price of the door existing.

Either way, one thing does not change hands: delivery. Neither Stripe nor Paddle invites anyone to a GitHub repository. Whoever you pick, that half of the sale is yours - which is the half the rest of this article builds.

## The delivery half Paddle doesn't do

Paddle's checkout has no buyer-facing custom field, so it cannot ask for a GitHub username on its own. RepoAccess closes that gap with a storefront the worker itself serves: the buyer opens `/checkout` on your domain, types their GitHub username into a labeled field, and pays inside Paddle's inline frame. The handle rides the transaction as `custom_data.github_username`, and on payment the buyer lands on the worker's delivery page with one instruction: check your email for the GitHub invitation.

If you already run your own site on Cloudflare, the storefront is optional: collect and confirm the username on your own page, open Paddle's checkout with the same `customData`, and drive delivery over the worker's service binding. Either way, no OAuth, no login - a typed handle and an email invite.

The webhook half subscribes to exactly three events:

```txt
transaction.completed            -> grant
adjustment.created / .updated    -> revoke (refund or chargeback)
```

The adjustment pair is where Merchant-of-Record correctness lives, because a Paddle refund is a lifecycle, not a moment. An adjustment arrives before it is approved, changes state, and may end approved, rejected, or partial - and not every adjustment may revoke access. The adapter classifies each one: an approved full refund or chargeback revokes; a pending or rejected adjustment is understood and deliberately left alone, and still gets its 200 so Paddle stops retrying a decision that was already made correctly.

Verification is the byte-exact kind this engine insists on everywhere: `Paddle-Signature: ts=<unix>;h1=<hex>`, HMAC-SHA256 over `ts` joined to the raw body with a literal colon - a dot, Stripe's separator, produces a valid-looking check that never passes. Trivia like that is exactly what costs an evening mid-launch, and exactly what ships pre-verified.

And when a buyer types a handle that cannot grant - malformed, or naming no GitHub account - the payment does not strand: the worker mints a single-use claim token and the buyer finishes on the claim page. The whole path above is live-verified against the real Paddle, sandbox and production: checkout, grant, refund and revoke, the partial-refund edge, and the claim fallback.

## An hour, two dashboards, and an agent that never sees your keys

Setup is the wizard from [the launch write-up](/en/blog/sell-access-private-github-repo/), with Paddle's screens in place of Stripe's. Your coding agent runs one command, renders one verified step at a time, and walks you through both dashboards: GitHub - the organization, the team that carries the repo, the token - and Paddle - the product, the webhook destination, the secrets. Budget roughly an hour end to end.

Every `done` is checked against real state where a check is possible, a failed check routes back to the screen that owns the wrong input, and the run ends with a test purchase against Paddle's sandbox - so the last screen of the setup is a grant you watched happen, not a promise. The secrets never pass through the agent: you paste them into the env file yourself, `wrangler` reads that file in its own process, and the permission rules denying the agent those reads ship committed in the repo.

It works on the cheapest models - my live Paddle runs used Claude Code on Haiku and OpenCode on a free bundled model - because the wizard owns the sequence and the wording, and the agent only renders and relays.

## What this costs, said plainly

The fee is real. Five percent plus fifty cents is more than bare Stripe charges, and if Stripe serves your country and you are comfortable owning tax in every jurisdiction you sell into, bare Stripe with the [free AGPL core](https://github.com/EdgeKits/repoaccess-core) is the cheaper stack. The MoR premium buys a legal counterparty, and it is worth exactly what not-owning-that is worth to you.

Paddle's onboarding is a review, not a signup form. Expect to describe your business, show your product, and wait for a human decision. That is the price of a platform that becomes the seller of record for strangers; plan days, not minutes, and have your product page live before you apply.

And the Paddle adapter is part of [RepoAccess Pro](/en/tools/repoaccess/), the paid tier - a one-time payment with twelve months of updates and support, which exists precisely because Merchant-of-Record correctness is maintenance work: adjustment lifecycles, payload shapes and signature schemes change on Paddle's schedule, and tracking that is the job you are buying out of.

## Sell your code from anywhere

That phrase is the whole reason this stack exists. The checkout belongs to a Merchant of Record that will take you, the delivery runs on a Cloudflare account that costs nothing to hold, and neither of them cares what your passport says. If Stripe's dropdown has been the wall between your code and its buyers, this is the way around it: [RepoAccess Pro with the Paddle adapter](/en/tools/repoaccess/), live-verified, deployed by your agent in about an hour.

## Frequently Asked Questions

**Q: What does it mean that Paddle is a Merchant of Record?**

**A:** Paddle resells your product to the buyer as its own: it is the legal seller on the receipt, it charges the card, it registers and remits sales tax in the buyer's jurisdiction, and it absorbs the disputes. You have one counterparty - Paddle - instead of a tax obligation in every country you sell into. Paddle charges 5% plus 50 cents per checkout for that role, against roughly 2.9% plus 30 cents for bare Stripe where you stay the seller of record.

---

**Q: Can I sell code online if Stripe is not available in my country?**

**A:** Yes, and the Merchant-of-Record route is the standard way. Stripe's supported list has 47 entries and India sits in preview behind contact-sales; most alternatives inherit that geography because their payouts run on Stripe rails. Paddle stands on its own rails and onboards sellers through a business verification review rather than a country dropdown, so the checkout works regardless of whether Stripe serves your country. Check Paddle's current terms for your jurisdiction, and expect the review to be real.

---

**Q: How does a buyer's GitHub username get collected in a Paddle checkout?**

**A:** Paddle's checkout has no buyer-facing custom field, so RepoAccess serves its own storefront: the buyer opens /checkout on your domain, types their GitHub username into a labeled field, and pays inside Paddle's inline frame. The handle travels as custom_data.github_username on the transaction, and after payment the buyer lands on the delivery page with one instruction - accept the GitHub invitation from email. Sellers with their own Cloudflare site can collect the handle on their own page instead and drive delivery over the worker's service binding.

---

**Q: How do refunds and chargebacks revoke GitHub access with Paddle?**

**A:** The worker subscribes to transaction.completed for grants and to adjustment.created and adjustment.updated for revokes. A Paddle refund is a lifecycle: an adjustment can be pending, approved, rejected or partial, and the adapter classifies each one - an approved full refund or a chargeback revokes the team membership, while a pending or rejected adjustment is deliberately left alone and still acknowledged, so Paddle stops retrying a decision that was already made. Revocation reconciles against live GitHub state, so retries are harmless.

---

**Q: How is a Paddle webhook signature verified?**

**A:** The Paddle-Signature header carries ts=<unix>;h1=<hex>, and the signed payload is the timestamp joined to the raw request body with a literal colon - not a dot, which is Stripe's separator. The HMAC-SHA256 runs over the byte-exact body, so parsing and re-serializing the JSON before verification breaks the signature. RepoAccess keeps the raw text, verifies with a constant-time comparison, and only then parses.

---

**Q: Is the Paddle adapter free?**

**A:** No. The AGPL core on npm is free and complete for the bare-Stripe path; the Paddle adapter ships in RepoAccess Pro, the paid tier, as a one-time payment with twelve months of updates and support. The pricing follows the work: Merchant-of-Record correctness is maintenance - adjustment lifecycles, payload shapes and signature schemes change on Paddle's schedule - and the paid tier exists to carry exactly that.

---

**Q: How long does the Paddle plus RepoAccess setup take?**

**A:** Budget roughly an hour end to end, dashboards included. A coding agent runs the setup wizard - one command, one verified step at a time across the GitHub and Paddle dashboards - and the run ends with a test purchase against Paddle's sandbox, so setup finishes on a grant you watched happen. Live runs used cheap models: Claude Code on Haiku and OpenCode on a free bundled model. Paddle's own account review is separate and takes days, so apply with your product page already live.