Skip to main content
Polar provides comprehensive customer management capabilities to help you track, organize, and engage with your customers effectively.

Overview

Customer management includes:
  • Centralized customer records
  • Customer profiles with metadata
  • Team customer accounts (multi-member)
  • Customer anonymization for GDPR compliance
  • External ID mapping for integration
Customers are automatically created when someone makes a purchase, but you can also create them manually via the API.

Customer Types

Polar supports two customer types:

Individual

Single person customers (default)

Team

Multi-member business accounts with seat management
Type Change Restriction: You cannot downgrade from team to individual after creation. Plan accordingly.

Creating Customers

Manual Creation

Create customers manually via the dashboard or API:
1

Navigate to Customers

Go to Dashboard > Customers > New Customer.
2

Enter Details

{
  "email": "[email protected]",
  "name": "Acme Corporation",
  "type": "team",
  "billing_address": {
    "country": "US"
  },
  "metadata": {
    "source": "enterprise_sales"
  }
}
3

Optional: Add Owner

For team customers, specify the primary owner:
{
  "owner": {
    "email": "[email protected]",
    "name": "John Doe"
  }
}

Automatic Creation

Customers are automatically created during:
  • Checkout completion
  • Subscription signup
  • First purchase

Customer Properties

Core Fields

Customer Object
{
  "id": "customer_xxx",
  "email": "[email protected]",
  "email_verified": true,
  "name": "Acme Corporation",
  "type": "team",
  "billing_address": {
    "country": "US",
    "line1": "123 Main St",
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94105"
  },
  "tax_id": "US123456789",
  "organization_id": "org_xxx",
  "created_at": "2024-01-01T00:00:00Z"
}

Email Verification

  • email_verified: Indicates if the customer’s email has been verified
  • Automatically set to true for customers who complete checkout
  • Set to false when email is updated

Billing Address

Customer billing addresses are used for:
  • Tax calculation
  • Invoice generation
  • Compliance requirements
Cannot Reset: Once a billing address is set, it cannot be removed (set to null). You can only update it to a different address.

External IDs

Map Polar customers to your own system:
Customer with External ID
{
  "email": "[email protected]",
  "external_id": "user_123_in_my_system"
}

External ID Rules

  • Must be unique within your organization
  • Can be set once and cannot be changed (immutable)
  • Useful for syncing with CRM, databases, or other systems
Query by External ID
const customer = await polar.customers.list({
  externalId: 'user_123_in_my_system'
});
External IDs are preserved during anonymization for legal/tax record-keeping.

Customer Metadata

Attach custom metadata to customers:
{
  "metadata": {
    "source": "referral",
    "campaign": "summer_2024",
    "segment": "enterprise",
    "sales_rep": "[email protected]"
  }
}
Metadata can be:
  • Searched and filtered via API
  • Included in webhooks
  • Used for segmentation and reporting

Querying by Metadata

const customers = await polar.customers.list({
  metadata: {
    segment: 'enterprise'
  }
});

Team Customers

Team customers support multiple members:

Owner Member

Every team customer has an owner:
Team Customer with Owner
{
  "email": "[email protected]",  // Billing email
  "name": "Acme Corporation",
  "type": "team",
  "owner": {
    "email": "[email protected]",      // Owner's personal email
    "name": "Jane Doe"
  }
}

Adding Members

Add team members for seat-based subscriptions:
await polar.members.create({
  customerId: 'customer_xxx',
  email: '[email protected]',
  role: 'member'
});
Search customers by:
  • Email (case-insensitive)
  • Name
  • External ID
  • Metadata
const results = await polar.customers.list({
  query: 'acme',  // Searches email, name, and external_id
  organizationId: 'org_xxx'
});

Updating Customers

Update customer information:
await polar.customers.update({
  id: 'customer_xxx',
  name: 'Acme Corp (Updated)',
  billingAddress: {
    country: 'US',
    line1: '456 New Address'
  }
});

Update Restrictions

  • ✅ Email: Can update (resets email_verified)
  • ✅ Name: Can update anytime
  • ✅ Billing Address: Can update but not remove
  • ❌ External ID: Cannot change once set
  • ❌ Type: Cannot downgrade from team to individual

Customer Deletion

Delete customers from your organization:
await polar.customers.delete({
  id: 'customer_xxx',
  anonymize: true  // Optional: Anonymize for GDPR
});

Deletion Behavior

  1. Subscriptions Canceled: All active subscriptions are canceled
  2. Benefits Revoked: Access to all benefits is removed
  3. Soft Delete: Customer is marked as deleted but data is retained
  4. Optional Anonymization: PII can be anonymized for GDPR compliance

GDPR Anonymization

Anonymize customer data for GDPR compliance:
await polar.customers.delete({
  id: 'customer_xxx',
  anonymize: true
});

What Gets Anonymized

  • ✅ Email → [email protected]
  • ✅ Name → [deleted] (for individuals without tax_id)
  • ✅ Billing Name → [deleted]
  • ✅ Billing Address → Removed
  • ✅ OAuth Tokens → Cleared
  • ❌ External ID → Preserved (legal/tax requirement)
  • ❌ Tax ID → Preserved (legal/tax requirement)
  • ❌ Business Name → Preserved (if tax_id exists)
Idempotent: Calling anonymize multiple times is safe and returns success without making changes.

Why Some Data is Preserved

Polar preserves certain data for legal compliance:
  • Tax IDs: Required for tax authority audits
  • External IDs: Needed for financial record reconciliation
  • Business Names: Required for business entities (those with tax_id)
  • Order History: Financial records must be retained

Customer State

Get a comprehensive view of a customer’s current state:
const state = await polar.customers.getState({
  id: 'customer_xxx'
});
Customer State
{
  "active_subscriptions": [
    {"id": "sub_xxx", "status": "active"}
  ],
  "granted_benefits": [
    {"id": "grant_xxx", "benefit_id": "benefit_xxx"}
  ],
  "active_meters": [
    {"id": "meter_xxx", "usage": 1500, "limit": 10000}
  ]
}
Customer state is cached for performance. It refreshes automatically when subscriptions or benefits change.

Webhooks

Customer-related webhook events:
  • customer.created: New customer created
  • customer.updated: Customer information changed
  • customer.deleted: Customer deleted/anonymized
  • customer.state_changed: Subscriptions, benefits, or meters changed
customer.state_changed Event
{
  "type": "customer.state_changed",
  "data": {
    "id": "customer_xxx",
    "active_subscriptions": [...],
    "granted_benefits": [...],
    "active_meters": [...]
  }
}

Best Practices

Use External IDs

Map Polar customers to your system for seamless integration

Enrich with Metadata

Add context about customer source, segment, and attributes

Verify Emails

Ensure email addresses are valid before important communications

Keep Addresses Current

Update billing addresses to ensure accurate tax calculation

Sorting and Pagination

Sort customer lists by:
  • Created date (default)
  • Email
  • Name
const customers = await polar.customers.list({
  sort: 'created_at',
  limit: 50,
  page: 1
});

API Reference

See the full API documentation:

Build docs developers (and LLMs) love