Search documentation of polar_express

# PolarExpress

Copy Markdown View Source

Comprehensive Elixir SDK for the Polar API, with verified 1:1 feature parity to the official JavaScript SDK.

> Note: This is an community Elixir SDK for Polar. Polar's official SDKs are in TypeScript/JavaScript and Python. This project is generated from the same OpenAPI spec that Polar uses to build their official SDKs, follows the same service architecture, and is structured to match the official JavaScript SDK. The goal is an idiomatic Elixir experience with the same API coverage.

### What's Included

The SDK layer provides typed resource structs, typed request params, and auto-paging pagination — all generated from the spec with full documentation. The client layer handles HTTP execution via Finch with connection pooling, automatic retries, request encoding, response deserialization, and telemetry.

Together, the complete Polar API surface is covered: 31 service modules, 30 typed resource structs, 85 typed params modules, webhook signature verification, and automatic pagination.

## Installation

### With Igniter (recommended for Phoenix)

> Beta: The Igniter installer is new and under active testing. Report issues here.

If your project uses Igniter, one command sets up everything — config, webhook plug, controller, and route:

    mix igniter.install polar_express

See the Igniter Installer guide for a detailed walkthrough of what the installer does.

### Manual

Add `polar_express` to your dependencies in `mix.exs`:

    def deps do
      [
        {:polar_express, "~> 0.1.5"}
      ]
    end

Requires Elixir 1.19+ and OTP 27+.

## Configuration

    # config/dev.exs — sandbox credentials
    config :polar_express,
      api_key: "pk_test_...",
      webhook_secret: "whsec_test_..."

    # config/runtime.exs — production credentials
    if config_env() == :prod do
      config :polar_express,
        api_key: System.fetch_env!("POLAR_ACCESS_TOKEN"),
        webhook_secret: System.fetch_env!("POLAR_WEBHOOK_SECRET")
    end

Optional global defaults (all have sensible defaults if omitted):

    config :polar_express,
      api_key: "pk_test_...",
      webhook_secret: "whsec_...",
      server: :sandbox,                  # :production or :sandbox, default: :production
      max_retries: 3,                    # default: 2
      timeout_ms: 30_000                 # request timeout in ms, default: 30_000

See the Getting Started guide for all config options and precedence rules.

## Quick Start

    client = PolarExpress.client()

    # Create a customer
    {:ok, customer} = PolarExpress.Services.CustomersService.create_customer(client, %{
      email: "jane@example.com"
    })

    # List products
    {:ok, products} = PolarExpress.Services.ProductsService.list_products(client, %{"limit" => 10})

    # Create a checkout
    {:ok, checkout} = PolarExpress.Services.CheckoutsService.create_checkout_session(client, %{
      "product_price_id" => "price_123",
      "success_url" => "https://example.com/success"
    })

Responses are automatically deserialized into typed structs:

    customer.id        #=> "cus_abc123"
    customer.email     #=> "jane@example.com"
    customer.__struct__ #=> PolarExpress.Resources.Customers

Override config per-client for multi-key or multi-server scenarios:

    client = PolarExpress.client(server: :sandbox)
    client = PolarExpress.client("pk_test_other_key", max_retries: 5)

## Features

### SDK

- Full API coverage — every endpoint from the Polar OpenAPI spec, with dedicated service modules matching the JavaScript SDK layout
- Typed resources — API responses are deserialized into typed Elixir structs with `@type t` definitions, full nesting support, and inner types
- Typed params — request parameters have dedicated struct modules with `@typedoc` annotations sourced from the OpenAPI spec
- Per-event typed modules — dedicated modules per webhook event type with typed data structs
- Auto-paging pagination — lazy `Stream`-based iteration for list endpoints
- Webhook verification — standardwebhooks signature verification with constant-time comparison and timestamp tolerance
- OAuth — `authorize_url`, `token`, and `deauthorize` for Polar OAuth flows
- Documentation — `@moduledoc`, `@doc`, `@typedoc`, `@spec`, and `@deprecated` on all generated modules, sourced from the OpenAPI spec

### Client

- Finch HTTP client — modern HTTP/2-capable client with connection pooling via NimblePool (replaces legacy Hackney)
- Automatic retries — exponential backoff with jitter for transient failures
- Request encoding — JSON request encoding with automatic multipart for file uploads
- Response deserialization — JSON to typed structs via object type registry
- Streaming — chunked response streaming for large payloads and SSE
- Telemetry — `:telemetry` events for request lifecycle observability
- Per-client configuration — explicit struct with no global state, safe for concurrent use with multiple API keys
- Test stubs — process-scoped HTTP stubs via NimbleOwnership for `async: true` tests

## Guides

- Getting Started — installation, configuration, first API call, pagination, error handling
- Igniter Installer — one-command Phoenix setup (beta)
- Webhooks — signature verification, WebhookPlug setup, typed event modules
- Testing — process-scoped HTTP stubs with `async: true` support
- Telemetry — request lifecycle events, logging, metrics

## Development

    # Sync the OpenAPI spec
    bash scripts/sync_openapi.sh

    # Generate the SDK
    mix polar.generate --clean --stats

    # Verify
    mix compile --warnings-as-errors
    mix test
    mix docs --warnings-as-errors
    bash scripts/diff_js.sh

### Code Generation

The SDK is auto-generated from Polar's OpenAPI spec via `mix polar.generate`. The generator produces:

- 31 service modules matching the JavaScript SDK layout
- 30 resource structs with `@type t` definitions and inner types
- 85 params modules with `@typedoc` field annotations
- 2 registries (object types and event types)
- 36 event modules for typed webhook event handling

A small set of overrides handle cases where the spec's metadata doesn't match the JavaScript SDK's service layout. Each override is documented with a reason and enforced by tests.

### Parity Testing

JavaScript SDK parity is a hard invariant. CI runs `scripts/diff_js.sh` to verify 1:1 service file and endpoint coverage. The test suite includes dedicated parity assertions comparing the generated endpoint set against both the OpenAPI spec and the JavaScript SDK fixture tree.

## License

MIT License. See `LICENSE` for details.

Next Page → Changelog