# JSON Merge API
> Deep-merge JSON objects — the operation every config and settings system needs. The merge endpoint recursively merges two objects (the second overrides the first), or a whole list of objects merged left-to-right, combining nested objects key by key rather than replacing them wholesale, with a choice of array strategy: replace (default), concat, union (concatenate and de-duplicate) or merge_index (merge element by element). A null in the overriding object can either overwrite the existing value or be ignored, so you can patch only the fields you mean to. The defaults endpoint is the inverse and just as useful: it fills in only the keys your data is missing from a defaults object, so your existing values always win — exactly how you layer a user's settings over default configuration. Everything is computed locally and deterministically, with no schema required. Ideal for configuration and feature-flag layering, settings and preference merges, combining API responses or partial updates, environment overrides, and template defaults. Pure local computation — no key, no third-party service, instant. Live, nothing stored. 3 endpoints. This merges documents; to diff or patch them (RFC 6902) use a JSON-diff API, to flatten them use a flatten API, and to address values use a JSON-Pointer 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/jsonmerge-api/..."
```

## Pricing
- **Free** (Free) — 4,135 calls/Mo, 2 req/s
- **Starter** ($6/Mo) — 13,650 calls/Mo, 8 req/s
- **Pro** ($26/Mo) — 187,500 calls/Mo, 20 req/s
- **Mega** ($64/Mo) — 980,000 calls/Mo, 50 req/s

## Endpoints

### Merge

#### `GET /v1/defaults` — Apply defaults

**Parameters:**
- `data` (query, required, string) — Your object (JSON) — its values win Example: `{"a":1}`
- `defaults` (query, required, string) — Defaults to fill missing keys (JSON) Example: `{"a":9,"b":2}`
- `array_strategy` (query, optional, string) — replace (default), concat, union or merge_index

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/jsonmerge-api/v1/defaults?data=%7B%22a%22%3A1%7D&defaults=%7B%22a%22%3A9%2C%22b%22%3A2%7D"
```

**Response:**
```json
{
    "data": {
        "result": {
            "a": 1,
            "b": 2
        },
        "array_strategy": "replace"
    },
    "meta": {
        "timestamp": "2026-06-03T17:42:22.107Z",
        "request_id": "55af14aa-52f1-4f4c-917d-9693f0a7a4a9"
    },
    "status": "ok",
    "message": "Apply defaults",
    "success": true
}
```

#### `GET /v1/merge` — Deep-merge objects

**Parameters:**
- `a` (query, optional, string) — Base object (JSON) Example: `{"a":1,"b":{"c":2}}`
- `b` (query, optional, string) — Overriding object (JSON) Example: `{"b":{"d":3},"e":4}`
- `objects` (query, optional, string) — Alternatively a JSON array of objects
- `array_strategy` (query, optional, string) — replace (default), concat, union or merge_index
- `null_strategy` (query, optional, string) — overwrite (default) or ignore

**Example:**
```bash
curl -H "x-oanor-key: $KEY" \
  "https://api.oanor.com/jsonmerge-api/v1/merge?a=%7B%22a%22%3A1%2C%22b%22%3A%7B%22c%22%3A2%7D%7D&b=%7B%22b%22%3A%7B%22d%22%3A3%7D%2C%22e%22%3A4%7D"
```

**Response:**
```json
{
    "data": {
        "result": {
            "a": 1,
            "b": {
                "c": 2,
                "d": 3
            },
            "e": 4
        },
        "sources": 2,
        "null_strategy": "overwrite",
        "array_strategy": "replace"
    },
    "meta": {
        "timestamp": "2026-06-03T17:42:22.207Z",
        "request_id": "bce488eb-3b87-4948-a4ba-332c1356f048"
    },
    "status": "ok",
    "message": "Deep-merge objects",
    "success": true
}
```

### Meta

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

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

**Response:**
```json
{
    "data": {
        "name": "JSON Merge API",
        "notes": "Send objects as JSON (POST body recommended). Nested objects merge recursively; arrays follow the chosen strategy. This merges documents — to diff or patch them (RFC 6902) use a JSON-diff API, and to flatten or address values use flatten / JSON-Pointer APIs. Nothing is stored.",
        "version": "v1",
        "endpoints": [
            {
                "path": "/v1/merge",
                "params": {
                    "a": "the base object (JSON)",
                    "b": "the overriding object (JSON)",
                    "objects": "alternatively, a JSON array of objects merged left-to-right",
                    "null_strategy": "overwrite (default) or ignore",
                    "array_strategy": "replace (default), concat, union or merge_index"
                },
                "returns": "the deep-merged object"
            },
            {
                "path": "/v1/defaults",
                "params": {
                    "data": "your object (JSON) — its values win",
                    "defaults": "the defaults to fill missing keys from (JSON)",
                    "array_strategy": "as merge"
                },
                "returns": "data with missing keys filled from defaults"
            },
            {
                "path": "/v1/meta",
                "params": [],
                "returns": "this document"
            }
        ],
        "description": "Deep-merge JSON o
…(truncated, see openapi.json for full schema)
```


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