> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.recursiv.io/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.recursiv.io/_mcp/server.

# Billing

## Overview

The Billing resource provides usage tracking, Stripe checkout/portal integration, and metered billing. The Settings resource manages user preferences, sessions, and account security. The Notifications resource handles push token registration.

## Billing (`r.billing`)

### Methods

| Method                                | Description                                                        |
| ------------------------------------- | ------------------------------------------------------------------ |
| `get(params)`                         | Get comprehensive billing info (customer, credits, subscriptions). |
| `getStatus(params)`                   | Get billing status for a user or organization.                     |
| `getPeriods(params)`                  | Get available billing periods with usage data.                     |
| `canCreateApiKey(params)`             | Check if user/org can create API keys.                             |
| `getUsage(params)`                    | Get usage summary for a billing period.                            |
| `getUsageByProject(params)`           | Get usage breakdown by project.                                    |
| `getUsageFromMeters(params)`          | Get usage from Stripe meters.                                      |
| `getProjectUsage(projectId, params?)` | Get usage for a specific project.                                  |
| `createCheckoutSession(input)`        | Create a Stripe Checkout session.                                  |
| `createPortalSession(input)`          | Create a Stripe Billing Portal session.                            |
| `ensureCustomer(params)`              | Ensure a Stripe customer exists.                                   |
| `recordAiUsage(input)`                | Record AI usage from a project.                                    |

### Get billing status

```typescript
const { data: status } = await r.billing.getStatus({
  organization_id: 'org_123',
});

console.log(status.has_stripe_account);
console.log(status.stripe_subscription_id);
console.log(status.status);              // 'active' | 'trialing' | 'past_due' | ...
console.log(status.has_payment_method);
```

**Owner parameters:**

All billing methods accept `user_id` or `organization_id` to scope the query:

| Parameter         | Type      | Description                         |
| ----------------- | --------- | ----------------------------------- |
| `user_id`         | `string?` | Scope to a user's personal billing. |
| `organization_id` | `string?` | Scope to an organization's billing. |

### Get usage summary

```typescript
const { data: usage } = await r.billing.getUsage({
  organization_id: 'org_123',
  year: 2025,
  month: 6,
});

console.log(`Sandbox compute: ${usage.sandbox_compute_hours}h`);
console.log(`Database compute: ${usage.database_compute_hours}h`);
console.log(`Database storage: ${usage.database_storage_gb}GB`);
console.log(`Object storage: ${usage.storage_gb}GB`);
console.log(`AI tokens: ${usage.ai_tokens}`);
console.log(`AI cost: $${(usage.ai_cost_cents / 100).toFixed(2)}`);
console.log(`Deployments: ${usage.deployment_compute_hours}h`);
console.log(`Total: $${(usage.total_cost_cents / 100).toFixed(2)}`);

// Line items
for (const item of usage.line_items) {
  console.log(`  ${item.name}: ${item.quantity} ${item.unit} = $${item.total_cost.toFixed(2)}`);
}
```

### Get usage by project

```typescript
const { data: projects } = await r.billing.getUsageByProject({
  organization_id: 'org_123',
  year: 2025,
  month: 6,
});

for (const p of projects) {
  console.log(`${p.project_name}:`);
  console.log(`  Sandbox: ${p.sandbox_compute_hours}h`);
  console.log(`  AI tokens: ${p.ai_tokens}`);
}
```

### Get specific project usage

```typescript
const { data: items } = await r.billing.getProjectUsage('proj_123', {
  from: '2025-06-01',
  to: '2025-06-30',
});

for (const item of items) {
  console.log(`${item.item}: ${item.units} ${item.unit_type}`);
}
```

### Available billing periods

```typescript
const { data: { periods } } = await r.billing.getPeriods({
  organization_id: 'org_123',
});

for (const period of periods) {
  console.log(`${period.label} (${period.year}-${period.month})`);
}
```

### Check API key creation eligibility

```typescript
const { data: { can_create } } = await r.billing.canCreateApiKey({
  organization_id: 'org_123',
});

if (!can_create) {
  console.log('Add a payment method to create API keys');
}
```

### Stripe Checkout (add payment method)

```typescript
const { data: checkout } = await r.billing.createCheckoutSession({
  organization_id: 'org_123',
  return_url: 'https://myapp.com/billing',
});

// Redirect user to checkout.url
console.log('Checkout URL:', checkout.url);
console.log('Session ID:', checkout.session_id);
```

### Stripe Billing Portal

```typescript
const { data: portal } = await r.billing.createPortalSession({
  organization_id: 'org_123',
  return_url: 'https://myapp.com/billing',
});

// Redirect user to portal.url for managing subscriptions
console.log('Portal URL:', portal.url);
```

### Ensure Stripe customer

Idempotently create a Stripe customer for a user or organization.

```typescript
const { data: customer } = await r.billing.ensureCustomer({
  organization_id: 'org_123',
});

console.log(customer.stripe_customer_id);
console.log(customer.is_new); // true if newly created
```

### Record AI usage

Record AI token usage from a project for metered billing.

```typescript
await r.billing.recordAiUsage({
  project_id: 'proj_123',
  input_tokens: 1500,
  output_tokens: 800,
  reasoning_tokens: 200,
  cost_cents: 0.05,
  provider_model: 'anthropic/claude-sonnet-4.6',
});
```

## Settings (`r.settings`)

### Methods

| Method                       | Description                   |
| ---------------------------- | ----------------------------- |
| `getPreferences()`           | Get user preferences.         |
| `updateNotifications(input)` | Update notification channels. |
| `updatePrivacy(input)`       | Update privacy settings.      |
| `updateAppearance(input)`    | Update appearance settings.   |
| `listSessions()`             | List active sessions.         |
| `revokeSession(id)`          | Revoke a session.             |
| `revokeAllSessions()`        | Revoke all sessions.          |
| `changePassword(input)`      | Change password.              |
| `requestEmailChange(input)`  | Request email change.         |
| `verifyEmailChange(token)`   | Verify email change.          |
| `requestDeletion(input?)`    | Request account deletion.     |
| `cancelDeletion()`           | Cancel account deletion.      |
| `getDeletionStatus()`        | Get deletion status.          |
| `getLoginHistory(params?)`   | Get login history.            |

### Get and update preferences

```typescript
const { data: prefs } = await r.settings.getPreferences();

console.log('Notifications:', prefs.notifications);
// { in_app: true, push: true, email: true }

console.log('Privacy:', prefs.privacy);
// { profile_visibility: 'public', show_email: false, show_location: true }

console.log('Appearance:', prefs.appearance);
// { theme: 'system', timezone: null, locale: null }

// Update notifications
await r.settings.updateNotifications({
  push: true,
  email: false,
});

// Update privacy
await r.settings.updatePrivacy({
  profile_visibility: 'network',
  show_email: false,
});

// Update appearance
await r.settings.updateAppearance({
  theme: 'dark',
  timezone: 'America/New_York',
});
```

### Session management

```typescript
// List active sessions
const { data: sessions } = await r.settings.listSessions();

for (const s of sessions) {
  console.log(`${s.user_agent} — ${s.ip_address}`);
  console.log(`  Current: ${s.is_current} — Expires: ${s.expires_at}`);
}

// Revoke a specific session
await r.settings.revokeSession('session_123');

// Revoke all sessions (nuclear option)
await r.settings.revokeAllSessions();
```

### Password management

```typescript
await r.settings.changePassword({
  current_password: 'oldPassword123',
  new_password: 'newSecurePassword456',
});
```

### Email change

```typescript
// Request change
const { data: result } = await r.settings.requestEmailChange({
  new_email: 'newemail@example.com',
  password: 'currentPassword123',
});

console.log(result.message);

// Verify with token (from email)
await r.settings.verifyEmailChange('verification_token_from_email');
```

### Account deletion

```typescript
// Request deletion
const { data: deletion } = await r.settings.requestDeletion({
  password: 'currentPassword123',
  confirm_text: 'DELETE MY ACCOUNT',
  reason: 'No longer using the service',
});

console.log(`Scheduled for: ${deletion.scheduled_at}`);

// Check status
const { data: status } = await r.settings.getDeletionStatus();
console.log(`Requested: ${status.requested}`);
console.log(`Grace period ends: ${status.grace_period_ends}`);

// Cancel within grace period
await r.settings.cancelDeletion();
```

### Login history

```typescript
const { data: history } = await r.settings.getLoginHistory({ limit: 10 });

for (const entry of history) {
  console.log(`${entry.created_at} — ${entry.ip_address} — ${entry.success ? 'OK' : 'FAILED'}`);
}
```

## Notifications (`r.notifications`)

### Methods

| Method                   | Description                           |
| ------------------------ | ------------------------------------- |
| `registerToken(input)`   | Register a push notification token.   |
| `unregisterToken(token)` | Unregister a push notification token. |

### Register push token

```typescript
await r.notifications.registerToken({
  token: 'ExponentPushToken[abc123...]',
  platform: 'expo',
  device_id: 'unique-device-id',
});
```

**Input fields:**

| Field       | Type                        | Required | Description               |
| ----------- | --------------------------- | -------- | ------------------------- |
| `token`     | `string`                    | Yes      | Push notification token.  |
| `platform`  | `'expo' \| 'fcm' \| 'apns'` | Yes      | Push provider platform.   |
| `device_id` | `string?`                   | No       | Unique device identifier. |

### Unregister push token

Call this on sign out to stop sending push notifications to a device.

```typescript
await r.notifications.unregisterToken('ExponentPushToken[abc123...]');
```