Loading page
escF1F2F3F4F5F6F7F8F9F10F11F12
~`!1@2#3$4%5^6&7*8(9)0_-+=delete
tabQWERTYUIOP{[}]|\
caps lockASDFGHJKL:;"'return
shiftZXCVBNM<,>.?/shift
fn⌃control⌥option⌘command⌘command⌥option◀▲▼▶
“Bounce it, sleep on it, listen again tomorrow.”
Learn how we integrated Polar payment platform into our team-based download system, enabling creators to monetize digital products with automated delivery and secure payments
Musicians selling their own files need a checkout that does not leak the file. Before the Polar integration, our teams faced several challenges: manual payment processing, no automated delivery, limited monetization options, and complex integration setup.
We've built a complete Polar integration that allows teams to set up their shop with organization tokens, create paid downloads with automatic product creation, automate delivery through custom benefits, and track sales directly. It runs on the download infrastructure teams already use.
// Teams configure their Polar integration
const polarTokenFormSchema = z.object({
polarOrganizationToken: z.string().min(1, 'Organization token is required'),
})
// Secure token validation and storage
export async function createPolarClientForTeam(teamId: number) {
const { data: teamData, error } =
await getTeamPolarOrganizationToken(teamId)
if (error || !teamData?.polar_organization_token) {
throw new Error('Polar integration not configured for this team')
}
return new Polar({
accessToken: teamData.polar_organization_token,
server: process.env.POLAR_ENVIRONMENT as 'production' | 'sandbox',
})
}
When a team creates a paid download, our system automatically validates the Polar integration, creates a product with the download details, sets up automated delivery through custom benefits, and links everything together. This eliminates manual work and ensures consistency.
// Create Polar product automatically
async function createPolarProduct(
polarClient: Polar,
title: string,
description: string,
price: number,
currency: string
) {
const product = await polarClient.products.create({
name: title || `Download ${Date.now()}`,
description: description || 'Digital download',
recurringInterval: null,
prices: [
price === 0
? { amountType: 'free' as const }
: {
amountType: 'fixed' as const,
priceAmount: Math.round(Math.max((price || 0) * 100, 1)),
priceCurrency: currency.toLowerCase(),
},
],
})
return product
}
// Create custom benefit for automated delivery
const customBenefit = await polarClient.benefits.create({
type: 'custom',
description: `Download access for: ${title}`,
properties: {
note: `Download URL: ${downloadLink.join(' , ')}\nTitle: ${title}\nDescription: ${description || 'Digital download'}`,
},
metadata: {
download_url: downloadLink.join(' , '),
download_title: title,
download_description: description || 'Digital download',
download_id: `${teamId}_${Date.now()}`,
benefit_type: 'custom',
automated_benefit: 'true',
},
})
The customer experience is streamlined with a secure checkout process. Customers browse downloads, fill out required information, click purchase to go to Polar checkout, complete payment securely, and automatically receive download links through the custom benefit system.
// Create secure checkout with success redirect
const checkout = await polarClient.checkouts.create({
products: [productId],
successUrl: `${process.env.NEXT_PUBLIC_BASE_URL}/@${teamSlug}/downloads/${downloadId}?paid=true`,
metadata: {
teamId,
type: 'download_purchase',
downloadId,
teamSlug,
},
})
// Customer gets redirected back after payment
// and automatically receives download access
Teams get powerful management capabilities including download analytics, flexible pricing in multiple currencies, customer data collection (email, name, phone), and social media integration requiring follows before download access. The system tracks everything automatically.
// Track download counts automatically
export const incrementDownloadCount = supabaseActionClient
.inputSchema(z.object({ downloadId: z.number() }))
.action(async ({ parsedInput: { downloadId }, ctx: { supabase } }) => {
const { data: currentData } = await supabase
.from('downloads')
.select('download_count')
.eq('id', downloadId)
.single()
const currentCount = currentData.download_count || 0
const newCount = currentCount + 1
const { data, error } = await supabase
.from('downloads')
.update({ download_count: newCount })
.eq('id', downloadId)
.select()
.single()
revalidateTag(`download_info_${data.track_id}`)
return { data, error }
})
// Customer data collection
const contactData = {
team_id: download.team_id!,
contact_group_id: [download.contact_group_id],
email,
first_name: firstName || null,
last_name: lastName || null,
phone_number: phoneNumber || null,
}
Our system gracefully handles various scenarios including missing Polar integration, failed product creation, invalid tokens, and network issues. We store Polar organization tokens securely and only use them server-side, implementing proper error handling throughout the system.
// Validate Polar integration before creating paid downloads
if (isPaid && (price || 0) > 0) {
const { data: polarIntegration } = await supabase
.from('team_integrations')
.select('*')
.eq('team_id', teamId)
.eq('integration_type', 'polar')
.eq('is_enabled', true)
.single()
if (!polarIntegration) {
return {
success: false,
message:
'Polar integration is required for paid downloads. Please set up your shop first.',
}
}
}
// Graceful fallback for product creation failures
try {
const product = await createPolarProduct(
polarClient,
title,
description,
price,
currency
)
polarProductId = product.id
} catch (productError) {
console.error('Error creating product:', productError)
polarProductId = null // Continue without product ID
}
We use Next.js caching strategies to optimize performance, cache team downloads, revalidate on updates, and optimize database queries. The system handles multiple audio players simultaneously with intelligent caching of last positions per track version.
// Cache invalidation on updates
revalidateTag(`team_downloads_${teamId}`)
revalidateTag(`general_download_${id}`)
revalidateTag(`user_teams_${user?.id}`)
// Optimized database queries with proper indexing
const { data: existingDownload } = await supabase
.from('downloads')
.select('polar_product_id')
.eq('id', id)
.single()
// Efficient product updates
if (existingDownload?.polar_product_id) {
polarProductId = existingDownload.polar_product_id
} else {
// Create new product only when needed
const product = await createPolarProduct(
polarClient,
title,
description,
price,
currency
)
polarProductId = product.id
}
Since implementing this Polar integration, teams have been able to increase revenue by monetizing previously free content, reduce manual work through automated delivery, shorten the purchase flow, and grow without taking on payment processing themselves.
For teams looking to set up Polar integration: create a Polar account at polar.sh/signup, set up your organization in the Polar dashboard, get your organization token from organization settings, configure the integration in your team's shop settings, and start creating paid downloads to earn money.
This Polar integration represents just the beginning of our monetization features. We're working on subscription models for ongoing content, tiered pricing for different access levels, bulk discounts for multiple purchases, and affiliate programs for team collaborations.
By integrating Polar into our team-based download system, teams can sell a file without hand-delivering it. The automated delivery system, combined with flexible pricing and customer data collection, provides teams with everything they need to build sustainable revenue streams from their content. The work went into hiding the plumbing from both the team and their customer.