# Duration API
> Work with ISO-8601 durations — the PnYnMnDTnHnMnS strings (P3Y6M4DT12H30M5S, PT1H30M) used across calendars, scheduling, video metadata, billing periods and APIs. Parse a duration into its components and a total in seconds and milliseconds; format a number of seconds (or individual year/month/week/day/hour/minute/second fields) back into a canonical ISO-8601 string; humanise any duration into readable text ("1 hour and 30 minutes"); and measure the exact duration between two instants (ISO timestamps or unix epochs) as both an ISO-8601 string and a precise second count. Years and months use documented calendar averages and are clearly flagged as approximate. Pure local computation — no key, no third-party service, instant. Live, nothing stored. 5 endpoints. Distinct from date/time parsing and relative-time ("3 hours ago") formatting.

## 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/duration-api/..."
```

## Pricing
- **Free** (Free) — 1,060 calls/Mo, 2 req/s
- **Starter** ($3/Mo) — 9,100 calls/Mo, 8 req/s
- **Pro** ($22/Mo) — 140,000 calls/Mo, 20 req/s
- **Mega** ($58/Mo) — 720,000 calls/Mo, 50 req/s

## Endpoints

### Duration

#### `GET /v1/between` — Duration between two instants

**Parameters:**
- `start` (query, required, string) — ISO date or unix ts Example: `2026-01-01T00:00:00Z`
- `end` (query, required, string) — ISO date or unix ts Example: `2026-01-02T03:04:05Z`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/duration-api/v1/between?start=2026-01-01T00%3A00%3A00Z&end=2026-01-02T03%3A04%3A05Z"
```

**Response:**
```json
{
    "data": {
        "end": "2026-01-02T03:04:05.000Z",
        "start": "2026-01-01T00:00:00.000Z",
        "iso8601": "P1DT3H4M5S",
        "direction": "end after start",
        "humanized": "1 day, 3 hours, 4 minutes and 5 seconds",
        "components": {
            "days": 1,
            "hours": 3,
            "weeks": 0,
            "years": 0,
            "months": 0,
            "minutes": 4,
            "seconds": 5
        },
        "total_seconds": 97445,
        "total_milliseconds": 97445000
    },
    "meta": {
        "timestamp": "2026-06-02T16:51:50.004Z",
        "request_id": "d61a2d5d-14cb-4610-813d-ff77c7b9d490"
    },
    "status": "ok",
    "message": "Duration between two instants",
    "success": true
}
```

#### `GET /v1/format` — Format seconds/components to ISO-8601

**Parameters:**
- `seconds` (query, optional, string) — Total seconds Example: `5400`
- `hours` (query, optional, string) — Hours field
- `minutes` (query, optional, string) — Minutes field
- `days` (query, optional, string) — Days field

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/duration-api/v1/format?seconds=5400"
```

**Response:**
```json
{
    "data": {
        "iso8601": "PT1H30M",
        "humanized": "1 hour and 30 minutes",
        "components": {
            "days": 0,
            "hours": 1,
            "weeks": 0,
            "years": 0,
            "months": 0,
            "minutes": 30,
            "seconds": 0
        },
        "total_seconds": 5400
    },
    "meta": {
        "timestamp": "2026-06-02T16:51:50.116Z",
        "request_id": "7e6afd5a-3ab8-4e4e-8170-67b6078439a5"
    },
    "status": "ok",
    "message": "Format seconds/components to ISO-8601",
    "success": true
}
```

#### `GET /v1/humanize` — Humanize a duration

**Parameters:**
- `duration` (query, optional, string) — ISO-8601 duration Example: `P1DT2H`
- `seconds` (query, optional, string) — Total seconds (alternative)

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/duration-api/v1/humanize?duration=P1DT2H"
```

**Response:**
```json
{
    "data": {
        "input": "P1DT2H",
        "humanized": "1 day and 2 hours",
        "total_seconds": 93600
    },
    "meta": {
        "timestamp": "2026-06-02T16:51:50.222Z",
        "request_id": "42d64a0e-d7a5-40ed-8969-8facd9e58e38"
    },
    "status": "ok",
    "message": "Humanize a duration",
    "success": true
}
```

#### `GET /v1/parse` — Parse an ISO-8601 duration

**Parameters:**
- `duration` (query, required, string) — ISO-8601 duration Example: `P3Y6M4DT12H30M5S`

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/duration-api/v1/parse?duration=P3Y6M4DT12H30M5S"
```

**Response:**
```json
{
    "data": {
        "note": "total_seconds uses calendar averages (1 month = 30.436875 days, 1 year = 365.2425 days)",
        "sign": "+",
        "input": "P3Y6M4DT12H30M5S",
        "humanized": "3 years, 6 months, 4 days, 12 hours, 30 minutes and 5 seconds",
        "components": {
            "days": 4,
            "hours": 12,
            "weeks": 0,
            "years": 3,
            "months": 6,
            "minutes": 30,
            "seconds": 5
        },
        "approximate": true,
        "total_seconds": 110839937,
        "total_milliseconds": 110839937000
    },
    "meta": {
        "timestamp": "2026-06-02T16:51:50.314Z",
        "request_id": "d309e54b-1578-497a-8008-bca2f73538fc"
    },
    "status": "ok",
    "message": "Parse an ISO-8601 duration",
    "success": true
}
```

### Meta

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

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

**Response:**
```json
{
    "data": {
        "name": "Duration API",
        "notes": "Years and months use calendar averages for total_seconds (flagged via `approximate`); /between is exact from the real timestamps.",
        "version": "v1",
        "endpoints": [
            {
                "path": "/v1/parse",
                "params": {
                    "duration": "ISO-8601 duration, e.g. P3Y6M4DT12H30M5S (required)"
                },
                "returns": "components, total_seconds, humanized"
            },
            {
                "path": "/v1/format",
                "params": {
                    "seconds": "number, OR",
                    "years_months_weeks_days_hours_minutes_seconds": "individual fields"
                },
                "returns": "ISO-8601 string + components"
            },
            {
                "path": "/v1/humanize",
                "params": {
                    "duration": "ISO-8601 string, OR seconds: number"
                },
                "returns": "human-readable text"
            },
            {
                "path": "/v1/between",
                "params": {
                    "end": "ISO date or unix ts (required)",
                    "start": "ISO date or unix ts (required)"
                },
                "returns": "exact duration between two instants"
            },
            {
                "path": "/v1/meta",
                "params": [],
                "returns": "this document"
            }
        
…(truncated, see openapi.json for full schema)
```


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