> ## Documentation Index
> Fetch the complete documentation index at: https://handbook.polar.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Platform API

> Proposal for a Platform API to enable partners to create and manage Polar Organizations on behalf of their users.

<Info>
  **Status**: Draft

  **Created**: 2025-02-13

  **Updated**: 2025-02-13
</Info>

# Overview

The Platform API enables partners to create and manage Polar Organizations on behalf of their users, allowing seamless integration of monetization features into third-party platforms. This document outlines the technical architecture, authentication flow, and claim process for the Platform API.

# Core Entities

## Platform Entity

A new `Platform` entity will be introduced to represent partners with access to the Platform API:

* **Purpose**: Represents external platforms that can create and manage Organizations
* **Key attributes**:
  * `id`: Unique identifier for the Platform
  * `name`: Human-readable name of the platform
  * `jwks_url`: URL where the platform exposes its JWKS (JSON Web Key Set)
  * `created_at`: Timestamp of platform creation
  * `updated_at`: Timestamp of last update

## Organization Enhancements

The existing `Organization` entity will be enhanced with platform-specific fields:

* **New fields**:
  * `platform_id` (nullable): Foreign key to the Platform that created/owns this Organization
  * `platform_external_id` (nullable): The Organization's ID on the external platform
  * `platform_created_at` (nullable): Timestamp when the Organization was created via Platform API

# Authentication Flow

## OIDC-based Authentication

The Platform API uses an OIDC approach with JWT tokens for authentication:

1. **Platform Setup**: Partner exposes JWKS at a public URL
2. **JWT Creation**: Platform creates a JWT signed with their private key
3. **Token Exchange**: JWT is sent to Polar's OAuth2 token endpoint
4. **Validation**: Polar validates the JWT using the platform's public key
5. **Access Token**: Polar returns an Organization Access Token

## JWT Structure

We support two types of JWTs for different use cases:

### Organization JWT (for Organization Access Tokens)

Used when the platform wants to act on behalf of a specific organization:

```json theme={null}
{
  "jti": "org-token-id-12345", // Unique ID for the token (single use)
  "sub": "org-external-123", // Platform's external organization ID
  "iss": "platform-123", // Platform ID
  "aud": "polar:platform-organization", // Audience: organization operations
  "organization_name": "Acme Inc", // Optional: Organization name (creation only)
  "organization_slug": "acme", // Optional: Organization slug (creation only)
  "iat": 1735689600, // Issued at timestamp
  "nbf": 1735689600, // Not before timestamp
  "exp": 1735776000 // Expiration timestamp
}
```

### Platform JWT (for Platform Access Tokens)

Used when the platform wants to perform platform-level operations:

```json theme={null}
{
  "jti": "platform-token-id-67890", // Unique ID for the token
  "sub": "platform-123", // Platform ID (subject)
  "iss": "platform-123", // Platform ID (issuer)
  "aud": "polar:platform", // Audience: platform operations
  "iat": 1735689600, // Issued at timestamp
  "nbf": 1735689600, // Not before timestamp
  "exp": 1735776000 // Expiration timestamp
}
```

**Key Differences:**

* **Organization JWT**: Contains organization-specific claims (`sub` = org external ID)
* **Platform JWT**: Contains only platform claims (`sub` = `iss` = platform ID)
* **Audience**: Different `aud` values determine token type

## Token Validation Process

The validation process differs based on the JWT type:

### Organization JWT Validation

1. **JWT Validation**: Verify signature using platform's JWKS
2. **Audience Check**: Ensure `aud` = `polar:platform-organization`
3. **Claim Extraction**: Extract `sub` (platform\_external\_id) and `iss` (platform\_id)
4. **Organization Lookup**: Query Organization by `platform_external_id` and `platform_id`
5. **Organization Creation** (if not exists):
   * Create new Organization using `organization_name` and `organization_slug` from JWT
   * Set `platform_id` and `platform_external_id`
6. **Access Token Issuance**: Return Organization Access Token

### Platform JWT Validation

1. **JWT Validation**: Verify signature using platform's JWKS
2. **Audience Check**: Ensure `aud` = `polar:platform`
3. **Claim Validation**: Ensure `sub` = `iss` = platform\_id
4. **Platform Verification**: Verify platform exists and is active
5. **Access Token Issuance**: Return Platform Access Token with requested scopes

# Organization Claim Flow

## Purpose

The claim flow allows a User to take ownership of an Organization created via the Platform API, enabling KYC completion and financial setup.

## Process

1. **Claim Token Generation**:
   * Platform calls `/api/platform/organizations/{platform_external_id}/claim_token`
   * Polar generates a short-lived, single-use claim token
   * Token contains: `organization_id`, `platform_id`, expiration

2. **User Onboarding**:
   * Platform presents claim token to their user
   * User visits Polar's onboarding flow with claim token
   * User creates Polar account (or logs in)

3. **Organization Claiming**:
   * User submits claim token during onboarding
   * Polar validates token and links User to Organization

4. **Post-Claim Process**:
   * User completes KYC verification
   * User sets up financial/payout details
   * Organization becomes fully active

# Platform Access Tokens

## Overview

In addition to Organization Access Tokens, we introduce Platform Access Tokens that allow platforms to manage multiple organizations and perform platform-level operations.

## Platform JWT Structure

Platforms can authenticate using a dedicated Platform JWT:

```json theme={null}
{
  "jti": "platform-token-id-67890", // Unique ID for the token
  "sub": "platform-123", // Platform ID (subject)
  "iss": "platform-123", // Platform ID (issuer)
  "aud": "polar:platform", // Audience: platform operations
  "iat": 1735689600, // Issued at timestamp
  "nbf": 1735689600, // Not before timestamp
  "exp": 1735776000 // Expiration timestamp
}
```

**Key differences from Organization JWT:**

* `sub` and `iss` are both the Platform ID
* `aud` is `polar:platform` (vs `polar:platform-organization` for org-specific operations)
* No organization-specific claims

## Platform Access Token Capabilities

Platform Access Tokens enable:

* Listing all organizations created by the platform
* Generating claim tokens for any platform organization
* Accessing platform-level analytics and reporting
* Managing platform configuration

## Token Exchange for Platform Access

```bash theme={null}
curl -X POST https://api.polar.sh/v1/oauth2/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "platform",
    "oidc_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
  }'
```

# API Endpoints

## Platform Authentication

* `POST /v1/oauth2/token` - Exchange JWT for access tokens
  * `grant_type: platform` with `aud: polar:platform` → Platform Access Token
  * `grant_type: platform` with `aud: polar:platform-organization` → Organization Access Token

## Organization Management (Platform Access)

* `GET /api/platform/organizations/` - List all platform organizations (requires Platform Access Token)
* `GET /api/platform/organizations/{platform_external_id}` - Get organization by external ID
* `POST /api/platform/organizations/{platform_external_id}/claim_token` - Generate claim token

## Organization Management (Organization Access)

* Standard Polar API endpoints (products, customers, subscriptions, etc.)

# Appendix: Sandbox as a Platform

Maybe a crazy idea, but we could consider the Polar Sandbox as a Platform on the Production environment. This would enable us to implement processes to automatically create an Organization in Production from a Sandbox!
