# Spoke Length & Wheel API
> Bicycle wheel-building maths as an API, computed locally and deterministically — the spoke-length and tension numbers a wheelbuilder laces a wheel by. The spoke endpoint runs the classic spoke-length formula from the hub and rim geometry: L = √(R² + r² + f² − 2·R·r·cos θ) − hole ÷ 2, where R is half the effective rim diameter (ERD), r is half the hub flange diameter, f is the centre-to-flange offset and θ = crosses × 720° ÷ spokes — so a 602 mm ERD rim on a 45 mm flange at 35 mm offset, 32 spokes laced 3-cross (a 67.5° crossing angle), needs a 293.9 mm spoke. It handles radial (0-cross) builds and computes the drive and non-drive sides separately from their own offsets, since a dished wheel’s two sides differ. The bracing endpoint gives each side’s bracing angle = atan(offset ÷ (ERD/2)) — the lever that resists side loads — and the resulting tension ratio, because the side with the smaller offset must carry higher tension, which is why a rear wheel’s non-drive spokes (often only about half the drive-side tension) go slack first. Everything is computed locally and deterministically, so it is instant and private. Ideal for bike-shop, wheelbuilding, cycling and bike-fit app developers, spoke-calculator and build-sheet tools, and component-database software. Pure local computation — no key, no third-party service, instant. Millimetres. Live, nothing stored. 2 compute endpoints. For gear inches or gearing use a bicycle-gear API.

## Authentication
All requests require your oanor API key in the `x-oanor-key` header. Get one at https://www.oanor.com/developer/keys.

```bash
curl -H "x-oanor-key: oanor_live_…" "https://api.oanor.com/spokelength-api/..."
```

## Pricing
- **Free** (Free) — 6,900 calls/Mo, 2 req/s
- **Starter** ($4/Mo) — 54,500 calls/Mo, 6 req/s
- **Pro** ($12/Mo) — 226,000 calls/Mo, 15 req/s
- **Mega** ($38/Mo) — 1,330,000 calls/Mo, 40 req/s

## Endpoints

### Wheel

#### `GET /v1/bracing` — Bracing angle + tension ratio

**Parameters:**
- `erd_mm` (query, required, string) — Effective rim diameter (mm) Example: `602`
- `offset_left_mm` (query, required, string) — Left/non-drive offset (mm) Example: `35`
- `offset_right_mm` (query, required, string) — Right/drive offset (mm) Example: `18`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/spokelength-api/v1/bracing?erd_mm=602&offset_left_mm=35&offset_right_mm=18"
```

**Response:**
```json
{
    "data": {
        "note": "Bracing angle = atan(offset ÷ (ERD/2)); a bigger angle braces the wheel better laterally. On a dished wheel the side with the SMALLER offset carries higher tension; the other side sits at offset_small ÷ offset_large of it. A low ratio (e.g. rear drive wheels ~0.5) is why non-drive spokes go slack first.",
        "inputs": {
            "erd_mm": 602,
            "offset_left_mm": 35,
            "offset_right_mm": 18
        },
        "higher_tension_side": "right",
        "bracing_angle_left_deg": 6.63,
        "bracing_angle_right_deg": 3.42,
        "looser_side_tension_ratio": 0.514
    },
    "meta": {
        "timestamp": "2026-06-06T07:14:02.260Z",
        "request_id": "5952d3b0-ba99-49c3-9e8c-a65b7ce7579f"
    },
    "status": "ok",
    "message": "Bracing + tension",
    "success": true
}
```

#### `GET /v1/spoke` — Spoke length

**Parameters:**
- `erd_mm` (query, required, string) — Effective rim diameter (mm) Example: `602`
- `flange_diameter_mm` (query, required, string) — Hub flange spoke-circle diameter (mm) Example: `45`
- `spokes` (query, required, string) — Total spoke count (even) Example: `32`
- `crosses` (query, required, string) — Cross pattern (0 = radial) Example: `3`
- `offset_mm` (query, optional, string) — Centre-to-flange offset (single side) Example: `35`
- `offset_left_mm` (query, optional, string) — Left/non-drive offset
- `offset_right_mm` (query, optional, string) — Right/drive offset
- `spoke_hole_mm` (query, optional, string) — Flange spoke-hole dia (default 2.6) Example: `2.6`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/spokelength-api/v1/spoke?erd_mm=602&flange_diameter_mm=45&spokes=32&crosses=3&offset_mm=35&spoke_hole_mm=2.6"
```

**Response:**
```json
{
    "data": {
        "note": "L = √(R² + r² + f² − 2·R·r·cos θ) − hole/2, with R = ERD/2, r = flange diameter/2, f = centre-to-flange offset, θ = crosses × 720° ÷ spokes. Round to the nearest 1 mm; build with the rounded length. Drive and non-drive sides usually differ.",
        "inputs": {
            "erd_mm": 602,
            "spokes": 32,
            "crosses": 3,
            "spoke_hole_mm": 2.6,
            "flange_diameter_mm": 45
        },
        "offset_mm": 35,
        "spoke_length_mm": 293.9,
        "crossing_angle_deg": 67.5
    },
    "meta": {
        "timestamp": "2026-06-06T07:14:02.344Z",
        "request_id": "c4ffc9a4-854d-49b3-8a27-2ca14edc79cf"
    },
    "status": "ok",
    "message": "Spoke length",
    "success": true
}
```

### Meta

#### `GET /v1/meta` — Spec

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/spokelength-api/v1/meta"
```

**Response:**
```json
{
    "data": {
        "notes": "Millimetres. ERD = effective rim diameter; offset = hub centre to flange. θ = crosses × 720° ÷ spokes (3-cross 32h = 67.5°). Compute drive and non-drive sides separately — they differ. For gearing or gear inches use a bicycle-gear API.",
        "service": "spokelength-api",
        "endpoints": {
            "GET /v1/meta": "This document.",
            "GET /v1/spoke": "Spoke length(s) from ERD, flange diameter, centre-to-flange offset, spoke count and cross pattern.",
            "GET /v1/bracing": "Bracing angles and side-to-side tension ratio for a dished wheel."
        },
        "description": "Bicycle wheel-building maths: spoke length from hub & rim geometry, bracing angles and dished-wheel tension ratio."
    },
    "meta": {
        "timestamp": "2026-06-06T07:14:02.410Z",
        "request_id": "a39e4b8d-7188-48b6-b18b-2721961b209c"
    },
    "status": "ok",
    "message": "Meta",
    "success": true
}
```


---
Marketplace page: https://www.oanor.com/api/spokelength-api
OpenAPI spec: https://www.oanor.com/api/spokelength-api/openapi.json
