- APPS
- Polar Payment Provider 17.0
| Lines of Code | 1792 |
| Technical name | payment_polar |
| License | OPL-1 |
| Website | https://viindoo.com/apps/modules/17.0/payment_polar |
| Read description for | v 18.0 |
| Required Apps | Invoicing (account) Discuss (mail) |
Accept card payments from anywhere. Skip the VAT paperwork everywhere.
Polar becomes the legal seller to your buyer: it charges the card, calculates and remits VAT in the buyer's own country, issues the buyer's invoice, and pays your company the net amount - already booked into your accounts.
Why merchants choose Polar
No VAT registration, anywhere.
Polar sells to your buyer directly, so Polar - not you - registers for and remits VAT in the buyer's country. You never file a foreign VAT return because of a Polar sale.
Every fee lands in your books.
When a Polar payment settles, the module posts one balanced entry automatically: net cash into a dedicated Polar clearing account, the receivable cleared at the full gross amount, and Polar's platform fee booked to its own expense account. Your accountant can trace every euro from checkout to journal entry.
126 currencies, one configuration.
Polar can charge your buyer in any of its 126 supported currencies as Merchant of Record, so there is no per-currency setup on your side. A built-in minimum-charge check stops an under-the-limit checkout before it ever reaches Polar.
Set up once, guarded from day one
- Polar appears as a standard payment provider in Accounting > Configuration > Payment Providers, configured the same way as any other provider.
- The Access Token and Webhook Secret are entered once, restricted to system administrators, and the webhook secret is password-masked on screen.
- The shared, reusable product every checkout needs is provisioned automatically the moment you enable the provider. If Polar was briefly unreachable at that instant, a one-click "Prepare Polar Product" button retries it - most admins never need to touch it.
- Odoo refuses to switch Polar to live or test mode until both the clearing account and the fee expense account are configured - a missing account is caught at setup, not mid-payment.
- A non-blocking warning banner flags anything else worth a look (invoicing settings, an unprepared product) without stopping you from saving.
A checkout your buyers already trust
- Buyers are redirected to Polar's own hosted checkout page to enter their card - your Odoo database never sees or stores card data.
- Sandbox and production are switched automatically by the same Test/Enabled toggle every other Odoo payment provider already uses.
- When a buyer returns from checkout, Odoo re-confirms the result directly with Polar's API rather than trusting the return URL.
Built to keep transactions moving
- Every webhook Polar sends is signature-verified before Odoo trusts it; a forged or expired signature is rejected outright.
- A webhook Odoo can't parse is discarded and logged, never crashes the endpoint - so one bad delivery can't take down every other transaction relying on the same webhook.
- If what Polar reports doesn't match what Odoo expected on settlement, the transaction is flagged as an error instead of silently posting the wrong amount.
- An hourly scheduled action re-checks any transaction still pending directly against Polar's API - the safety net if a webhook is delayed, lost, or the endpoint stops receiving them.
- If Polar's API is rate-limited mid-run, the check simply picks up again next hour instead of failing the batch.
Refunds without leaving Odoo
Issue a full or partial refund from the same Refund action you already use for every other provider; Odoo calls Polar's API against the original order and tracks the refund as its own transaction until Polar confirms it.
How It Works
Activate Polar
Add your Organization Access Token and Webhook Secret from your Polar dashboard.
Point the accounting
In Settings > Accounting, set the Polar Clearing Account and the Polar Fee Expense Account. From here, Odoo wires the clearing account onto the payment method automatically.
Go live
Switch the provider to Enabled. Odoo checks both accounts are set, then provisions the shared checkout product automatically before it lets you save.
Buyer pays
At checkout, the buyer is redirected to Polar, pays in their own currency, and receives their invoice from Polar as Merchant of Record.
Odoo settles automatically
The webhook (or, if one is ever missed, next hour's scheduled poll) confirms the order and books the net cash, gross receivable, and platform fee in a single entry.
Refund if needed
One click from the same transaction, exactly like any other provider.
From Checkout to Journal Entry
Most payment connectors stop at "payment received." This one keeps going into the ledger.
The moment Polar confirms an order paid, the module posts a single balanced payment move: the net amount Polar actually pays you lands in a dedicated Polar Clearing Account, the customer's receivable is cleared at the full gross amount, and Polar's platform fee is booked straight to an expense account you choose. Nothing is estimated after the fact, and nothing needs a manual journal entry.
If Polar reports its fee in a currency other than the one the buyer paid in, the module converts it before posting, so the entry is correctly valued - not just numerically balanced.
Because the clearing account is dedicated to Polar alone, your accountant can always tell Polar's net cash apart from every other payment provider's - which is what makes the next step, matching Polar's bank payout, straightforward: standard Odoo bank reconciliation, by date and amount, against that one account.
Scope & Good to Know
- Payout matching is a manual date-and-amount match, by design. Polar pays out in aggregate - one payout can bundle several orders - and does not expose a payout-to-order mapping to connected apps. The module isolates Polar's net cash in its own dedicated clearing account specifically so your accountant matches it with Odoo's standard bank-reconciliation widget, the same way as any other bank line.
- Disputes and chargebacks stay in Polar's dashboard. Polar does not send a dispute webhook, so a dispute shows up in your payout figures, not as a separate Odoo record.
- No saved cards. Each checkout is a fresh session on Polar's hosted page; there is no one-click repeat payment.
- If Polar ever stops delivering webhooks to your endpoint, the hourly scheduled poll keeps every pending transaction moving on its own - you re-enable the endpoint from the Polar dashboard when you're ready.
Technical Requirement
- Odoo 17 with the Accounting app installed.
- A Polar.sh organization with an Organization Access Token and a Standard-Webhooks signing secret.
- The Polar Clearing Account and Polar Fee Expense Account configured in Settings > Accounting before the provider can be enabled.
- Automatic Invoice turned on (Settings > Sales), so each Polar checkout produces an invoice. With it off, Polar still collects the full prepayment as Merchant of Record and the payment sits as an unreconciled customer prepayment until you invoice it manually - Odoo warns you on the provider form if Polar is active without it.
- Licensed under OPL-1.
Need help with Polar Payment Provider?
User Guide: Polar Payment Provider
This guide explains how to configure and use the Polar Payment Provider module for online payments through Polar.sh.
Note
Polar acts as a Merchant of Record. Polar takes the buyer's card payment, computes and remits VAT itself, issues its own invoice to the buyer, deducts a platform fee, and pays you the net amount. Odoo never sees the buyer's card details and never calculates VAT on a Polar sale: its job is to record the payment against your ordinary accounts, check that each webhook really came from Polar, and let you refund from Odoo.
Installation
- Navigate to Apps.
- Search with the keyword payment_polar.
- Press Install.
Before You Enable Polar
Polar needs very little setting up before you switch it on. There are no dedicated Polar accounts to configure - Polar works with your standard payment accounts out of the box. What Odoo does insist on is a usable bank journal, and it is worth turning on Automatic Invoice as well. If Odoo refuses to switch the provider on, the message names the one thing to fix, so you can work through the points below in any order.
No dedicated account setup is needed
Unlike some integrations, Polar has no dedicated accounts to set up. Straight out of the box it uses the same standard accounts every other online payment provider uses: the cash a buyer pays lands in your company's Outstanding Receipts account, and Polar's platform fee is reconciled against your bank statement, exactly like a card processor's fee. Enabling Polar on a brand-new Chart of Accounts simply works - there is nothing to configure here first.
Check the company's bank journal
The company that owns the provider needs a usable bank journal, because that is what Odoo uses to record Polar's incoming cash. Odoo blocks activation otherwise, and tells you which of the two situations you are in:
- If the bank journal exists but is archived, Odoo names it and asks you to unarchive it. An archived journal is unusable, so a provider whose company has one can look correctly set up and still refuse to switch on. Do not build a second journal next to it - bring the existing one back.
- If the company has no active bank journal at all, Odoo asks you to create one, or to unarchive an existing one.
Turn on Automatic Invoice
Polar collects the full payment as Merchant of Record, which can happen before Odoo has an invoice for the sale. Go to the Sales ‣ Configuration ‣ Settings menu, open the Invoicing section, and turn on Automatic Invoice so every order paid online - including through Polar - is invoiced automatically as soon as the payment is confirmed.
Configure the provider
Polar ships Disabled, and you will find it under Invoicing ‣ Configuration ‣ Online Payments ‣ Payment Providers (Accounting ‣ Configuration ‣ Online Payments ‣ Payment Providers if you use the Accounting app).
Open Polar, then work through these steps in order:
- Set the State to Test Mode or Enabled before anything else. This is the first step, not the last: while the provider is Disabled, Odoo cannot tell whether to talk to Polar's sandbox or to Polar's production service, so it refuses to create anything in Polar at all. The form says so, and both buttons below refuse with the same explanation if you press them too early. Choose Test Mode to work against Polar's sandbox, or Enabled to work against Polar production.
- On the Credentials tab, fill in the Polar Access Token: the Organization Access Token from your Polar dashboard, which authenticates every call Odoo makes. It must include the webhooks:write scope, or the next step fails. Sandbox and production each need their own token.
- Save, then press Generate your webhook. Odoo asks Polar to create
the webhook endpoint for this database and fills in both Polar Webhook
Secret and Polar Webhook Endpoint Reference for you. You no longer
register anything by hand in the Polar dashboard, and you never have to
find or copy your Odoo webhook address.
- The Polar Webhook Secret is what lets Odoo tell a real Polar message from a forged one. If you ever paste it yourself instead of using the button, copy it exactly as Polar shows it, including the whsec_ prefix.
- The Polar Webhook Endpoint Reference is filled in for you and cannot be typed by hand. Odoo uses it for the hourly endpoint health check, which reports in this provider's warning banner if Polar has disabled the endpoint.
- Leave Polar Product Reference alone. Odoo provisions the one shared, reusable Polar product that every checkout references the moment you save the provider in Test Mode or Enabled - you do not do this by hand. The Prepare Polar Product button is only there to retry if that automatic attempt did not go through.
The yellow banner at the top of the provider lists anything still missing - the shared product, the webhook secret, the bank journal, or automatic invoicing - one problem per line, each naming its own fix. It is the fastest way to see what is left to do.
Trying Polar out in Test Mode
In Test Mode, Odoo talks to Polar's sandbox instead of the real thing. The sandbox is a separate server with its own account, organisation and access token - your production token will not work there, and nothing you do in it touches real money.
The provider form links straight to Polar's sandbox setup guide. Once you are set up, pay with the test card 4242 4242 4242 4242, any future expiry date and any CVC. Polar's sandbox settles cards through Stripe, so the full list of test cards lives in Stripe's documentation.
Changing the access token later
If you replace the Polar Access Token, Odoo clears the webhook secret, the webhook endpoint reference and the product reference, and provisions the product again with the new token.
This is deliberate, and it is worth understanding before you swap a token by mistake. A token belongs to exactly one Polar organization, and Polar's sandbox is a physically separate server from production - so everything the old token created is meaningless to the new one. After changing the token, press Generate your webhook again to create a fresh webhook endpoint.
How a Polar Checkout Works
When a buyer pays with Polar, Odoo creates a Polar checkout session for a single, tax-inclusive line item and redirects the buyer's browser to Polar's own hosted checkout page. Polar handles the card capture, the VAT calculation and its own buyer-facing invoice end to end; Odoo never collects or stores the card details.
A Polar checkout can present the buyer with, and charge them in, any of the 126 currencies Polar supports. As Merchant of Record, Polar computes and remits that jurisdiction's VAT itself - no currency-conversion configuration is needed for this, and none is allowed on a Polar provider. Before redirecting the buyer, Odoo also checks the amount against Polar's documented per-currency minimum charge and blocks with a clear message if it is too low, rather than letting the checkout fail on Polar's side.
When the buyer's browser returns from the hosted checkout, Odoo does not trust the returned parameters at face value: it re-fetches the authoritative checkout state directly from Polar's API before showing the buyer the payment status.
Note
An illustration of the hosted checkout page itself is pending - it is served by Polar, and reaching it requires live Polar credentials.
How Settlement Is Booked in Odoo
The moment Polar confirms an order is paid, Odoo books the payment automatically, with no manual journal work. Out of the box - with no dedicated Polar accounts set up - Polar settles exactly like any other online payment provider:
- The full gross amount clears the customer's receivable and lands in your company's standard Outstanding Receipts account.
- Polar's platform fee stays inside that payment. It is not booked as a separate expense; instead it surfaces later, when Polar's payout - the gross amount minus its fee - arrives in your bank and you reconcile that deposit against the payment, the same place any card processor's fee is reconciled (see Payout reconciliation is manual, by design, below).
Note
Advanced users can optionally isolate Polar's cash in a dedicated account and book each fee to its own expense account by setting the Polar Clearing Account and Polar Fee Expense Account fields on the company record through the developer tools; left unset - the normal case - the standard flow above applies.
Issuing a Refund
You can issue a full or partial refund of a settled Polar payment directly from the standard Odoo refund action on the transaction. Odoo calls Polar's refund API against the original Polar order and tracks the refund as its own transaction, staying pending until Polar confirms it succeeded.
Note
An illustration of the refund flow is pending - it requires a real settled Polar payment to refund.
The Hourly Poll Cron: Your Safety Net
Every hour, the Polar: poll pending transactions scheduled action re-checks every Polar transaction still in draft or pending from the last 7 days directly against Polar's API, and settles or updates it from that authoritative state.
This is the safety net for a webhook delivery that never arrived - and, if Polar disables the endpoint after repeated delivery failures, the hourly poll keeps your transactions moving until you re-enable the endpoint from Polar's own dashboard.
Troubleshooting: Checkout Fails Right After Enabling
Odoo provisions the shared Polar product automatically the moment you enable the provider. If Polar was unreachable at that exact moment (for example, the access token was not valid yet), that automatic attempt is only logged as a warning - it never blocks saving the provider - and the product reference stays empty. The first checkout then fails with a clear error instead of charging anyone incorrectly.
To fix it, open the Polar provider and press Prepare Polar Product to retry. It is safe to press even if the product was already provisioned: the action does nothing if a product reference is already set.
Troubleshooting: Payments Only Confirm Once an Hour
If Polar payments reach Odoo late, in an hourly batch rather than within seconds, the webhook is not getting through and the poll cron is carrying the whole load. The provider's warning banner names the reason:
- No webhook secret is set. Press Generate your webhook to create one.
- Polar auto-disabled the webhook endpoint after repeated delivery failures. Re-enable it from the Polar dashboard; the banner clears by itself once Polar reports the endpoint healthy again.
What You Need to Know Before Going Live
Payout reconciliation is manual, by design
Polar's payouts API cannot be called with the access token an Odoo server holds, so Odoo can never learn which orders a given payout settled. This module does not try to guess. Polar's cash rides your standard Outstanding Receipts account, and when a Polar payout - the net amount, after the platform fee - lands in your bank, your accountant matches that deposit against the payments behind it in Odoo's own bank-reconciliation widget, using the amount and the date as the matching signal. The platform fee shows up right here, as the gap between the gross payments and the net deposit. This is a reconciliation heuristic, not an authoritative, order-by-order match - plan your reconciliation process accordingly.
Polar exposes no dispute or chargeback webhook
This module does not receive or process any dispute or chargeback event, because Polar does not emit a webhook for them. Disputes are handled entirely in Polar's own dashboard, and reach Odoo only indirectly, through the payout figures your accountant reconciles.
Turn on Automatic Invoice, or expect an uninvoiced prepayment
Polar collects the full payment as Merchant of Record before Odoo necessarily has an invoice for it. If Automatic Invoice (see the Turn on Automatic Invoice section above) is turned off, a Polar checkout lands in Odoo as an unreconciled customer prepayment until an invoice is created by hand. The Polar provider form warns about exactly this as long as the setting stays off; turn it on so every settled Polar payment is invoiced automatically.
This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file).
You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one).
It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software.
The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.