# Offset Orders

An **Offset Order** represents an order placed on Wren to remove a certain amount of carbon dioxide (or CO₂ equivalents) from the atmosphere using projects in a [Portfolio](https://www.wren.co/docs/api/portfolios). When you create an offset order, our system records the amount of CO₂ removed and pays the respective project partners for carbon credits at the end of each month.

## POST /api/offset-orders — Create offset orders

Creates offset orders by allocating a given number of tons across the projects in a portfolio. Funds are distributed according to the portfolio's allocation percentages.

POST`/api/offset-orders`Copy Path

### Authentication

Required. Use a **team API token** (recommended) or legacy personal API token via Basic auth or Bearer token. Account (password, Google, or Shopify) required for personal tokens. **Test tokens** (`wren_test_…`) return canned responses without DB writes, Stripe charges, or notifications — full validation still runs. See [Test mode](https://www.wren.co/docs/api#test-mode).

### Headers

- `Content-Type: application/json` or `application/x-www-form-urlencoded`

### Request body

| Attribute | Type | Description & Constraints |
| --- | --- | --- |
| `tons` | number | **Required.** Amount of CO₂e to offset in tonnes. |
| `portfolioId` | number | Optional. Portfolio ID for allocation. Default: Wren Climate Fund. |
| `note` | string | Optional. Note attached to each order. |
| `dryRun` | boolean | Optional. If true, no charge is made; returns preview only. |
| `sendReceiptEmail` | boolean | Optional. If true, sends a receipt email when `dryRun` is `false`. |
| `paymentMethod` | string | Optional. `"stripe"` (default) or `"credits"`. When `"credits"`, deducts from your credit balance instead of charging Stripe. No $1 minimum when using credits. |
| `onBehalfOfName` | string | Optional. Name of the end-customer this order is being placed for. Shown as the purchaser on the impact certificate. Max 200 characters. |
| `onBehalfOfEmail` | string | Optional. Email of the end-customer this order is being placed for. Stored alongside the order; not used for sending email. Max 320 characters. |

### Minimum amount

- `tons` must be positive.
- When `paymentMethod` is `"stripe"` (default): total charge must be at least 100 USD cents ($1). Minimum tons depends on portfolio `cost_per_ton`.
- When `paymentMethod` is `"credits"`: no minimum charge — any positive `tons` value is accepted, as long as you have sufficient credit balance.

### Example request

### Success response

HTTP `200`

- `id` — Stripe charge ID, or `null` when `dryRun=true`
- `amountCharged` — In the user currency's smallest denomination (e.g. 5000 = $50.00)

When `paymentMethod` is `"credits"`, the response also includes:

- `paymentMethod` — `"credits"`
- `creditsRemaining` — Remaining credit balance in USD cents after the order

### Error responses

- **400** — Invalid payload, missing `tons`, charge below minimum, or insufficient credit balance
- **403** — Missing/invalid auth or not an account user

* * *

## GET /api/offset-orders — List your offset orders

Returns the authenticated user's offset orders with aggregate stats.

GET`/api/offset-orders`Copy Path

### Authentication

Required. Use a team API token or legacy personal API token via Basic auth or Bearer token. Test tokens return a small canned sample list.

### Request

No body. No query parameters.

### Success response

HTTP `200`

- `stats.totalTons` — Sum of certified and external-standard offset tons
- `stats.rank` / `stats.percentile` — User's global ranking (omitted when `totalTons` is 0)
- `offsetOrders` — Certified offset orders (snake_case fields)
- `uncertifiedOffsetOrders` — Offsets not meeting certified standards
- `amount_paid_by_customer` — USD cents. Typically integer-valued, but sub-cent fractional values can appear on rows from credit-funded sub-dollar orders, where a small charge is split across multiple projects.

### Error responses

- **403** — Missing or invalid authentication

* * *

## GET /api/offset-orders/public — List public offset orders

Returns a curated list of public offset orders for display (e.g. leaderboards, feeds). No authentication required. Data is cached and refreshed hourly.

GET`/api/offset-orders/public`Copy Path

### Authentication

None required.

### Request

No body. No query parameters.

### Success response

HTTP `200`

- Up to 30 orders, sorted by most recent
- Each row aggregates one user's charge per portfolio
