{
  "components": {
    "headers": {
      "Allow": {
        "description": "Comma-separated list of HTTP methods supported on this resource (RFC 7231 §6.5.5). Emitted on every 405 response.",
        "schema": {
          "type": "string"
        }
      },
      "RateLimitPolicy": {
        "description": "Sustained rate-limit policy as `\u003cquota\u003e;w=\u003cwindow-seconds\u003e` (e.g. `60;w=60` = 60 requests per 60 seconds). The burst ceiling in X-RateLimit-Limit is higher; throughput sustained above this policy is eventually throttled with a 429.",
        "schema": {
          "type": "string"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before retrying.",
        "schema": {
          "type": "integer"
        }
      },
      "WWWAuthenticate": {
        "description": "RFC 7235 authentication challenge. Always `Bearer realm=\"trakrf-api\"` on 401 responses.",
        "schema": {
          "type": "string"
        }
      },
      "XRateLimitLimit": {
        "description": "Maximum requests allowed in a single burst before a 429 — the rate-limit bucket's ceiling. The lower *sustained* rate is advertised separately in the RateLimit-Policy header.",
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitRemaining": {
        "description": "Requests remaining before a 429. Decrements by one on every request, from X-RateLimit-Limit down to 0; clients may pace on this value. Refills over time toward the ceiling at the sustained rate (see RateLimit-Policy).",
        "schema": {
          "type": "integer"
        }
      },
      "XRateLimitReset": {
        "description": "Unix timestamp (seconds) when X-RateLimit-Remaining will next equal X-RateLimit-Limit — i.e. when the bucket has fully refilled to the ceiling. Equals the current time when Remaining is already at the ceiling.",
        "schema": {
          "type": "integer"
        }
      },
      "XRequestId": {
        "description": "Server-assigned request correlation identifier; mirrored as error.request_id in error envelopes and echoed in server logs. Quote this when filing support tickets.",
        "schema": {
          "type": "string"
        }
      }
    },
    "schemas": {
      "AddAssetTagResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Tag"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "AddLocationTagResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/Tag"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "AssetHistoryItem": {
        "properties": {
          "duration_seconds": {
            "format": "int32",
            "nullable": true,
            "type": "integer"
          },
          "event_observed_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "type": "string"
          },
          "location_external_key": {
            "nullable": true,
            "type": "string"
          },
          "location_id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "nullable": true,
            "type": "integer"
          }
        },
        "required": [
          "event_observed_at",
          "location_id",
          "location_external_key",
          "duration_seconds"
        ],
        "type": "object"
      },
      "AssetHistoryResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/AssetHistoryItem"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "AssetLocationItem": {
        "properties": {
          "asset_deleted_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "asset_external_key": {
            "type": "string"
          },
          "asset_id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "type": "integer"
          },
          "asset_last_seen": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "type": "string"
          },
          "dwell_seconds": {
            "format": "int32",
            "type": "integer"
          },
          "dwell_started_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "type": "string"
          },
          "location_external_key": {
            "nullable": true,
            "type": "string"
          },
          "location_id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "nullable": true,
            "type": "integer"
          }
        },
        "required": [
          "asset_id",
          "asset_external_key",
          "location_id",
          "location_external_key",
          "asset_last_seen",
          "asset_deleted_at"
        ],
        "type": "object"
      },
      "AssetLocationsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/AssetLocationItem"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "AssetView": {
        "properties": {
          "created_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "deleted_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "description": {
            "nullable": true,
            "type": "string"
          },
          "external_key": {
            "type": "string"
          },
          "id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "readOnly": true,
            "type": "integer"
          },
          "is_active": {
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": true,
            "type": "object"
          },
          "name": {
            "type": "string"
          },
          "tags": {
            "description": "Tags currently attached to this resource. Read-only on PATCH; mutate via POST /{resource}/{id}/tags and DELETE /{resource}/{id}/tags/{tag_id}.",
            "items": {
              "$ref": "#/components/schemas/Tag"
            },
            "readOnly": true,
            "type": "array"
          },
          "updated_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "valid_from": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "id",
          "external_key",
          "name",
          "description",
          "metadata",
          "is_active",
          "valid_from",
          "valid_to",
          "created_at",
          "updated_at",
          "deleted_at",
          "tags"
        ],
        "type": "object"
      },
      "BarcodeTag": {
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. On this read schema the `tag_type` enum carries `x-extensible-enum: true` (an OpenAPI 3.0 vendor extension) to mark it open to additive variants; promoting that marker to native OpenAPI 3.1 enum semantics is a deferred migration.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "properties": {
          "id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "readOnly": true,
            "type": "integer"
          },
          "tag_type": {
            "description": "Discriminator for the polymorphic Tag resource. `rfid` denotes an RFID transponder, `ble` denotes a Bluetooth Low Energy beacon, and `barcode` denotes a 1D/2D barcode. Together with `value`, this forms the natural key — the same `value` may exist under different `tag_type`s without conflict.",
            "enum": [
              "barcode"
            ],
            "type": "string",
            "x-extensible-enum": true
          },
          "value": {
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          }
        },
        "required": [
          "id",
          "tag_type",
          "value"
        ],
        "type": "object"
      },
      "BarcodeTagRequest": {
        "additionalProperties": false,
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. The request `tag_type` enum is intentionally closed: it carries no `x-extensible-enum` marker, and a write naming an unrecognized variant is rejected as described above.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "properties": {
          "tag_type": {
            "description": "Discriminator for the polymorphic Tag resource. `rfid` denotes an RFID transponder, `ble` denotes a Bluetooth Low Energy beacon, and `barcode` denotes a 1D/2D barcode. Together with `value`, this forms the natural key — the same `value` may exist under different `tag_type`s without conflict.",
            "enum": [
              "barcode"
            ],
            "type": "string"
          },
          "value": {
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          }
        },
        "required": [
          "tag_type",
          "value"
        ],
        "type": "object"
      },
      "BleTag": {
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. On this read schema the `tag_type` enum carries `x-extensible-enum: true` (an OpenAPI 3.0 vendor extension) to mark it open to additive variants; promoting that marker to native OpenAPI 3.1 enum semantics is a deferred migration.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "properties": {
          "id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "readOnly": true,
            "type": "integer"
          },
          "tag_type": {
            "description": "Discriminator for the polymorphic Tag resource. `rfid` denotes an RFID transponder, `ble` denotes a Bluetooth Low Energy beacon, and `barcode` denotes a 1D/2D barcode. Together with `value`, this forms the natural key — the same `value` may exist under different `tag_type`s without conflict.",
            "enum": [
              "ble"
            ],
            "type": "string",
            "x-extensible-enum": true
          },
          "value": {
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          }
        },
        "required": [
          "id",
          "tag_type",
          "value"
        ],
        "type": "object"
      },
      "BleTagRequest": {
        "additionalProperties": false,
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. The request `tag_type` enum is intentionally closed: it carries no `x-extensible-enum` marker, and a write naming an unrecognized variant is rejected as described above.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "properties": {
          "tag_type": {
            "description": "Discriminator for the polymorphic Tag resource. `rfid` denotes an RFID transponder, `ble` denotes a Bluetooth Low Energy beacon, and `barcode` denotes a 1D/2D barcode. Together with `value`, this forms the natural key — the same `value` may exist under different `tag_type`s without conflict.",
            "enum": [
              "ble"
            ],
            "type": "string"
          },
          "value": {
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          }
        },
        "required": [
          "tag_type",
          "value"
        ],
        "type": "object"
      },
      "CreateAssetResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AssetView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "CreateAssetWithTagsRequest": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "example": "Main warehouse forklift",
            "maxLength": 1024,
            "minLength": 1,
            "nullable": true,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          },
          "external_key": {
            "description": "external_key is optional. Omit to receive a server-assigned key in the\nformat ASSET-NNNN (per-organization sequence). When supplied, must\nsatisfy the external_key_pattern.",
            "example": "forklift-3",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9-]+$",
            "type": "string"
          },
          "is_active": {
            "example": true,
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": {},
            "type": "object"
          },
          "name": {
            "example": "Forklift 3",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^\\S(?:[^\\x00-\\x1F\\x7F]*\\S)?$",
            "type": "string"
          },
          "tags": {
            "items": {
              "$ref": "#/components/schemas/TagRequest"
            },
            "nullable": true,
            "type": "array"
          },
          "valid_from": {
            "example": "2025-01-01T00:00:00Z",
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "example": "2026-01-01T00:00:00Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "type": "object"
      },
      "CreateLocationResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LocationView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "CreateLocationWithTagsRequest": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "example": "Main warehouse location",
            "maxLength": 1024,
            "minLength": 1,
            "nullable": true,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          },
          "external_key": {
            "description": "external_key is optional. Omit to receive a server-assigned key in the\nformat LOC-NNN (per-organization sequence, 3-digit zero-pad), parallel\nto (but narrower than) assets' ASSET-NNNN behavior. When supplied,\nmust satisfy the external_key_pattern.",
            "example": "wh1",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9-]+$",
            "type": "string"
          },
          "is_active": {
            "example": true,
            "type": "boolean"
          },
          "name": {
            "example": "Warehouse 1",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^\\S(?:[^\\x00-\\x1F\\x7F]*\\S)?$",
            "type": "string"
          },
          "parent_external_key": {
            "example": "wh1",
            "maxLength": 255,
            "minLength": 1,
            "nullable": true,
            "pattern": "^[A-Za-z0-9-]+$",
            "type": "string"
          },
          "parent_id": {
            "example": 42,
            "format": "int64",
            "maximum": 9007199254740991,
            "minimum": 1,
            "nullable": true,
            "type": "integer"
          },
          "tags": {
            "items": {
              "$ref": "#/components/schemas/TagRequest"
            },
            "nullable": true,
            "type": "array"
          },
          "valid_from": {
            "example": "2025-12-14T00:00:00Z",
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "example": "2026-12-14T00:00:00Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "type": "object"
      },
      "ErrorEnvelope": {
        "description": "TrakRF error envelope, modeled on RFC 7807 but not 7807-compliant. Carried nested under `error.*` on every error response; content-type is `application/json` (not `application/problem+json`). Generated clients should branch on `type` and `title`, not `detail`. `title` is a stable, machine-readable summary that does not vary between calls for the same condition. `detail` is the specific, human-readable cause of this particular failure and may be empty when title alone fully describes the condition.",
        "properties": {
          "detail": {
            "description": "Specific, human-readable cause of this particular failure. May be empty when title alone fully describes the condition. Do not branch on this value.",
            "type": "string"
          },
          "fields": {
            "items": {
              "$ref": "#/components/schemas/FieldError"
            },
            "type": "array"
          },
          "instance": {
            "type": "string"
          },
          "request_id": {
            "type": "string"
          },
          "status": {
            "format": "int32",
            "type": "integer"
          },
          "title": {
            "description": "Stable, machine-readable summary suitable for client-side branching. Does not vary between calls for the same condition.",
            "type": "string"
          },
          "type": {
            "$ref": "#/components/schemas/ErrorType"
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "instance",
          "request_id"
        ],
        "type": "object"
      },
      "ErrorResponse": {
        "properties": {
          "error": {
            "$ref": "#/components/schemas/ErrorEnvelope"
          }
        },
        "required": [
          "error"
        ],
        "type": "object"
      },
      "ErrorType": {
        "description": "Machine-readable error envelope discriminator. Pairs with `title` and `detail` to drive client-side branching on a stable token (per RFC 9457).",
        "enum": [
          "validation_error",
          "bad_request",
          "unauthorized",
          "forbidden",
          "not_found",
          "conflict",
          "rate_limited",
          "internal_error",
          "method_not_allowed",
          "unsupported_media_type",
          "missing_org_context",
          "payment_required",
          "capability_required"
        ],
        "example": "validation_error",
        "type": "string",
        "x-extensible-enum": true
      },
      "FieldError": {
        "properties": {
          "code": {
            "$ref": "#/components/schemas/FieldErrorCode"
          },
          "field": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "params": {
            "additionalProperties": {},
            "type": "object"
          }
        },
        "required": [
          "field",
          "code",
          "message"
        ],
        "type": "object"
      },
      "FieldErrorCode": {
        "description": "Machine-readable field-level validation error code. Identifies which constraint a request payload violated; pairs with the field path and human-readable message in a FieldError entry.",
        "enum": [
          "required",
          "invalid_value",
          "unknown_field",
          "too_short",
          "too_long",
          "too_small",
          "too_large",
          "fk_not_found",
          "ambiguous_fields",
          "read_only",
          "invalid_context"
        ],
        "example": "required",
        "type": "string",
        "x-extensible-enum": true
      },
      "GetAssetResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AssetView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "GetCurrentOrgResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/OrgView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "GetLocationResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LocationView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "ListAssetsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/AssetView"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "ListLocationAncestorsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/LocationView"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "ListLocationChildrenResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/LocationView"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "ListLocationDescendantsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/LocationView"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "ListLocationsResponse": {
        "properties": {
          "data": {
            "items": {
              "$ref": "#/components/schemas/LocationView"
            },
            "type": "array"
          },
          "limit": {
            "example": 50,
            "format": "int32",
            "type": "integer"
          },
          "offset": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          },
          "total_count": {
            "example": 100,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "limit",
          "offset",
          "total_count"
        ],
        "type": "object"
      },
      "LocationView": {
        "properties": {
          "created_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "deleted_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "nullable": true,
            "readOnly": true,
            "type": "string"
          },
          "description": {
            "nullable": true,
            "type": "string"
          },
          "external_key": {
            "type": "string"
          },
          "id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "readOnly": true,
            "type": "integer"
          },
          "is_active": {
            "type": "boolean"
          },
          "name": {
            "type": "string"
          },
          "parent_external_key": {
            "nullable": true,
            "type": "string"
          },
          "parent_id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "nullable": true,
            "type": "integer"
          },
          "tags": {
            "description": "Tags currently attached to this resource. Read-only on PATCH; mutate via POST /{resource}/{id}/tags and DELETE /{resource}/{id}/tags/{tag_id}.",
            "items": {
              "$ref": "#/components/schemas/Tag"
            },
            "readOnly": true,
            "type": "array"
          },
          "updated_at": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "readOnly": true,
            "type": "string"
          },
          "valid_from": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "example": "2025-04-29T12:34:56.000Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "required": [
          "id",
          "external_key",
          "name",
          "description",
          "parent_id",
          "parent_external_key",
          "is_active",
          "valid_from",
          "valid_to",
          "created_at",
          "updated_at",
          "deleted_at",
          "tags"
        ],
        "type": "object"
      },
      "OrgView": {
        "properties": {
          "api_key_id": {
            "example": "550e8400-e29b-41d4-a716-446655440000",
            "type": "string"
          },
          "id": {
            "example": 42,
            "format": "int64",
            "maximum": 9007199254740991,
            "readOnly": true,
            "type": "integer"
          },
          "name": {
            "example": "Acme Logistics",
            "type": "string"
          },
          "scopes": {
            "example": [
              "assets:read",
              "assets:write"
            ],
            "items": {
              "type": "string"
            },
            "type": "array"
          }
        },
        "required": [
          "id",
          "name",
          "scopes",
          "api_key_id"
        ],
        "type": "object"
      },
      "RenameAssetRequest": {
        "additionalProperties": false,
        "properties": {
          "external_key": {
            "example": "ASSET-0042",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9-]+$",
            "type": "string"
          }
        },
        "required": [
          "external_key"
        ],
        "type": "object"
      },
      "RenameAssetResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AssetView"
          },
          "descendant_count_affected": {
            "example": 0,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "descendant_count_affected"
        ],
        "type": "object"
      },
      "RenameLocationRequest": {
        "additionalProperties": false,
        "properties": {
          "external_key": {
            "example": "wh1",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[A-Za-z0-9-]+$",
            "type": "string"
          }
        },
        "required": [
          "external_key"
        ],
        "type": "object"
      },
      "RenameLocationResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LocationView"
          },
          "descendant_count_affected": {
            "example": 7,
            "format": "int32",
            "type": "integer"
          }
        },
        "required": [
          "data",
          "descendant_count_affected"
        ],
        "type": "object"
      },
      "RfidTag": {
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. On this read schema the `tag_type` enum carries `x-extensible-enum: true` (an OpenAPI 3.0 vendor extension) to mark it open to additive variants; promoting that marker to native OpenAPI 3.1 enum semantics is a deferred migration.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "properties": {
          "id": {
            "format": "int64",
            "maximum": 9007199254740991,
            "readOnly": true,
            "type": "integer"
          },
          "tag_type": {
            "description": "Discriminator for the polymorphic Tag resource. `rfid` denotes an RFID transponder, `ble` denotes a Bluetooth Low Energy beacon, and `barcode` denotes a 1D/2D barcode. Together with `value`, this forms the natural key — the same `value` may exist under different `tag_type`s without conflict.",
            "enum": [
              "rfid"
            ],
            "type": "string",
            "x-extensible-enum": true
          },
          "value": {
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          }
        },
        "required": [
          "id",
          "tag_type",
          "value"
        ],
        "type": "object"
      },
      "RfidTagRequest": {
        "additionalProperties": false,
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. The request `tag_type` enum is intentionally closed: it carries no `x-extensible-enum` marker, and a write naming an unrecognized variant is rejected as described above.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "properties": {
          "tag_type": {
            "description": "Discriminator for the polymorphic Tag resource. `rfid` denotes an RFID transponder, `ble` denotes a Bluetooth Low Energy beacon, and `barcode` denotes a 1D/2D barcode. Together with `value`, this forms the natural key — the same `value` may exist under different `tag_type`s without conflict.",
            "enum": [
              "rfid"
            ],
            "type": "string"
          },
          "value": {
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          }
        },
        "required": [
          "tag_type",
          "value"
        ],
        "type": "object"
      },
      "Tag": {
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. On this read schema the `tag_type` enum carries `x-extensible-enum: true` (an OpenAPI 3.0 vendor extension) to mark it open to additive variants; promoting that marker to native OpenAPI 3.1 enum semantics is a deferred migration.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "discriminator": {
          "mapping": {
            "barcode": "#/components/schemas/BarcodeTag",
            "ble": "#/components/schemas/BleTag",
            "rfid": "#/components/schemas/RfidTag"
          },
          "propertyName": "tag_type"
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/RfidTag"
          },
          {
            "$ref": "#/components/schemas/BleTag"
          },
          {
            "$ref": "#/components/schemas/BarcodeTag"
          }
        ]
      },
      "TagRequest": {
        "description": "Polymorphic identifier attached to an asset or location, discriminated by `tag_type` into one of three variants: `RfidTag` (RFID transponder, `tag_type: rfid`), `BleTag` (Bluetooth Low Energy beacon, `tag_type: ble`), or `BarcodeTag` (1D/2D barcode, `tag_type: barcode`). The `/assets/{asset_id}/tags` and `/locations/{location_id}/tags` subresources accept and return all three variants; `tag_type` together with `value` form the natural key (a tag value is unique within its kind, not across kinds). \n\n`tag_type` is an **open** enumeration per the versioning policy — new variants may be added in additive minor revisions without a `/api/v2` cut. Integrators should treat unknown `tag_type` values as forward-compatible: pass the row through untouched rather than rejecting it. \n\n**Read direction is open; write direction is closed.** The open-enumeration semantic applies to **response handling**: if a `GET` returns a `tag_type` value your client doesn't recognize, pass the row through untouched rather than rejecting it (additive variants may appear in minor revisions). The **write surface is closed**: `POST /tags` and the natural-key tuple `(tag_type, value)` accept only the currently-defined variants (`rfid`, `ble`, `barcode`). Writes carrying an unrecognized `tag_type` are rejected with `400 validation_error` / `code: invalid_value` / `params.allowed_values: [...]`. The asymmetry is intentional — forward-compatibility on read, strict validation on write. The request `tag_type` enum is intentionally closed: it carries no `x-extensible-enum` marker, and a write naming an unrecognized variant is rejected as described above.\n\n**Codegen note:** some strict-typed generators (e.g. datamodel-codegen for Pydantic) materialize the single-value `tag_type` constants on each variant as separate enum classes — `TagType`, `TagType2`, `TagType4` or similar. That is a generator artifact and not part of the contract; the wire shape is a single discriminated union with three variants today. Treat the generated classes as implementation detail.",
        "discriminator": {
          "mapping": {
            "barcode": "#/components/schemas/BarcodeTagRequest",
            "ble": "#/components/schemas/BleTagRequest",
            "rfid": "#/components/schemas/RfidTagRequest"
          },
          "propertyName": "tag_type"
        },
        "oneOf": [
          {
            "$ref": "#/components/schemas/RfidTagRequest"
          },
          {
            "$ref": "#/components/schemas/BleTagRequest"
          },
          {
            "$ref": "#/components/schemas/BarcodeTagRequest"
          }
        ]
      },
      "TokenRequest": {
        "properties": {
          "client_id": {
            "example": "6f1c2a8e-7d3b-4e90-9a11-2c4d5e6f7a8b",
            "type": "string"
          },
          "client_secret": {
            "example": "trakrf_9f8e7d6c5b4a39281706f5e4d3c2b1a0ffeeddccbbaa99887766554433221100",
            "type": "string"
          },
          "grant_type": {
            "enum": [
              "client_credentials",
              "refresh_token"
            ],
            "example": "client_credentials",
            "type": "string"
          },
          "refresh_token": {
            "example": "f3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            "type": "string"
          }
        },
        "required": [
          "grant_type"
        ],
        "type": "object"
      },
      "TokenResponse": {
        "properties": {
          "access_token": {
            "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.short-lived-access-jwt",
            "type": "string"
          },
          "expires_in": {
            "example": 900,
            "format": "int32",
            "type": "integer"
          },
          "refresh_token": {
            "example": "f3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
            "type": "string"
          },
          "token_type": {
            "example": "Bearer",
            "type": "string"
          }
        },
        "required": [
          "access_token",
          "refresh_token",
          "token_type",
          "expires_in"
        ],
        "type": "object"
      },
      "UpdateAssetRequest": {
        "properties": {
          "description": {
            "example": "Updated description",
            "maxLength": 1024,
            "minLength": 1,
            "nullable": true,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          },
          "is_active": {
            "example": true,
            "type": "boolean"
          },
          "metadata": {
            "additionalProperties": {},
            "type": "object"
          },
          "name": {
            "example": "Forklift 3",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^\\S(?:[^\\x00-\\x1F\\x7F]*\\S)?$",
            "type": "string"
          },
          "valid_from": {
            "example": "2025-01-01T00:00:00Z",
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "example": "2026-01-01T00:00:00Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "UpdateAssetResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AssetView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      },
      "UpdateLocationRequest": {
        "properties": {
          "description": {
            "example": "Updated description",
            "maxLength": 1024,
            "minLength": 1,
            "nullable": true,
            "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
            "type": "string"
          },
          "is_active": {
            "example": true,
            "type": "boolean"
          },
          "name": {
            "example": "Warehouse 1",
            "maxLength": 255,
            "minLength": 1,
            "pattern": "^\\S(?:[^\\x00-\\x1F\\x7F]*\\S)?$",
            "type": "string"
          },
          "parent_external_key": {
            "example": "wh1",
            "maxLength": 255,
            "minLength": 1,
            "nullable": true,
            "pattern": "^[A-Za-z0-9-]+$",
            "type": "string"
          },
          "parent_id": {
            "example": 42,
            "format": "int64",
            "maximum": 9007199254740991,
            "minimum": 1,
            "nullable": true,
            "type": "integer"
          },
          "valid_from": {
            "example": "2025-12-14T00:00:00Z",
            "format": "date-time",
            "type": "string"
          },
          "valid_to": {
            "example": "2026-12-14T00:00:00Z",
            "format": "date-time",
            "nullable": true,
            "type": "string"
          }
        },
        "type": "object"
      },
      "UpdateLocationResponse": {
        "properties": {
          "data": {
            "$ref": "#/components/schemas/LocationView"
          }
        },
        "required": [
          "data"
        ],
        "type": "object"
      }
    },
    "securitySchemes": {
      "BearerAuth": {
        "bearerFormat": "JWT",
        "description": "TrakRF API access token. Format: \"Bearer \u003caccess_token\u003e\". Create API credentials in the API Keys section of your TrakRF account to obtain a {client_id, client_secret} pair, then exchange them at POST /oauth/token (grant_type=client_credentials) for a short-lived access token; send that token here. Some OpenAPI generators (e.g. openapi-fetch, openapi-generator-cli python target) do not auto-attach the Authorization header from this scheme — set it manually if your generated client does not. Similarly, some generated clients (notably openapi-fetch) do not auto-attach `Content-Type: application/merge-patch+json` on PATCH operations, even though the operation's requestBody.content lists only that media type; set the header manually per PATCH call if your client does not.",
        "scheme": "bearer",
        "type": "http"
      }
    }
  },
  "info": {
    "contact": {
      "email": "support@trakrf.id",
      "name": "TrakRF Support",
      "url": "https://trakrf.id"
    },
    "description": "TrakRF public REST API. See /api for the customer-facing reference. Integrator-focused Markdown documentation: https://docs.trakrf.id/llms-api.txt\n\nSpec available as YAML (/api/openapi.yaml) and JSON (/api/openapi.json).\n\nHTTP method coverage (HEAD, OPTIONS, 405 / Allow): /docs/api/http-method-coverage\n\nNullable field interpretation: OpenAPI 3.0's `nullable: true` keyword is interpreted differently across codegen targets. Verified-working: `openapi-typescript@7.x` emits `string | null` correctly, and the `openapi-generator-cli` python target emits `Optional[StrictStr]` correctly — both round-trip CRUD against null-bearing responses unmodified. Known-broken: `datamodel-codegen@0.57.0` emits `nullable: true` read-shape fields as non-Optional required fields, so Pydantic validation fails on every nullable field that is actually null. Integrators using `datamodel-codegen` should either switch to the `openapi-generator-cli` python target or apply `--use-annotated --use-union-operator` with a custom post-processing pass.",
    "license": {
      "name": "Business Source License 1.1",
      "url": "https://github.com/trakrf/platform/blob/main/LICENSE"
    },
    "title": "TrakRF API",
    "version": "1.0.0",
    "x-package-name": "trakrf-api-client"
  },
  "openapi": "3.0.3",
  "paths": {
    "/api/v1/assets": {
      "get": {
        "description": "**Required scope:** `assets:read`\n\nPaginated assets list with natural-key filters, sort, and substring search.\n\nDefault scope returns currently-effective assets only — rows whose `valid_from` is in the past AND whose `valid_to` is null or in the future. The `is_active` filter is independent of temporal validity; omit it to include both active and inactive rows within the effective window, or pass `?is_active=true`/`false` to filter further.",
        "operationId": "listAssets",
        "parameters": [
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "filter by asset external_key, equality match (may repeat for any-of)",
            "explode": true,
            "in": "query",
            "name": "external_key",
            "schema": {
              "default": [],
              "items": {
                "pattern": "^[A-Za-z0-9-]+$",
                "type": "string"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by active flag",
            "in": "query",
            "name": "is_active",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "when true, include soft-deleted rows in the response. deleted_at is populated for those rows. Orthogonal to is_active.",
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "description": "substring search (case-insensitive) on name, external_key, description, and active tag values",
            "in": "query",
            "name": "q",
            "schema": {
              "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
              "type": "string"
            }
          },
          {
            "description": "comma-separated; prefix '-' for DESC",
            "explode": false,
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "",
              "pattern": "^(|(?:external_key|-external_key|name|-name|created_at|-created_at|updated_at|-updated_at)(?:,(?:external_key|-external_key|name|-name|created_at|-created_at|updated_at|-updated_at))*)$",
              "type": "string"
            },
            "style": "form"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListAssetsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Bad Request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Not Found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Internal Server Error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List assets",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:read"
        ]
      },
      "post": {
        "description": "**Required scope:** `assets:write`\n\nCreate a new asset record, optionally with one or more tags (RFID, BLE, barcode).\n\nThe `external_key` field is optional. Provide a value from your system of record\n(ERP, WMS, asset management) for natural-key joins, or omit it to receive a\nserver-assigned external_key in the format `ASSET-NNNN` (per-organization sequence).\nA caller-supplied external_key that collides with an existing asset returns 409.\n\nReturns the created asset with its assigned tags. The Location response header contains the path of the created resource (resolve against the request URL per RFC 7231 §7.1.2).",
        "operationId": "createAsset",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateAssetWithTagsRequest"
              }
            }
          },
          "description": "Asset to create with optional tags",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateAssetResponse"
                }
              }
            },
            "description": "Created",
            "headers": {
              "Location": {
                "description": "Path of the created resource (resolve against request URL per RFC 7231 §7.1.2)",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Create an asset",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/api/v1/assets/{asset_id}": {
      "delete": {
        "description": "**Required scope:** `assets:write`\n\nDelete an asset by its canonical id. The asset is removed from all subsequent queries and its external_key becomes immediately available for reuse. Returns 204 on success, 404 if the asset does not exist or has already been deleted.",
        "operationId": "deleteAsset",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "deleted",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Delete an asset",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:write"
        ]
      },
      "get": {
        "description": "**Required scope:** `assets:read`\n\nRetrieve an asset by its canonical id. Returns 404 if the asset does not exist.\n\nPath-addressed retrieval bypasses the temporal-validity filter applied on list endpoints — any non-deleted asset is returned regardless of its `valid_from` / `valid_to` values. Use this endpoint when you have an id and need the row even if its effective window has elapsed.",
        "operationId": "getAsset",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetAssetResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Bad Request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Not Found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Internal Server Error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get asset by canonical id",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:read"
        ]
      },
      "patch": {
        "description": "**Required scope:** `assets:write`\n\nApply a JSON Merge Patch (RFC 7396) to an asset. Only fields included in the request body are changed; fields set to `null` clear the corresponding nullable column. Omitted fields are left unchanged. Every accepted PATCH — empty body (`{}`), verbatim echo of current values, partial mutation, or full mutation — advances `updated_at` on success (filesystem `touch` semantics). Read-only fields are uniformly governed by the accept-if-matches, reject-if-differs rule: a value matching the current resource state is silently normalized out (so a verbatim GET → PATCH round-trip succeeds without manual scrubbing), and a differing value returns 400. The rejection `code` splits the two semantic classes: server-managed fields (`id`, `created_at`, `updated_at`, `deleted_at`) return `code: read_only` — they have no public mutation path. Fields mutable via a sub-resource verb (`external_key`, `tags`) return `code: invalid_context` and the detail names the correct verb: mutate `external_key` via POST /assets/{asset_id}/rename; mutate `tags` via POST /assets/{asset_id}/tags and DELETE /assets/{asset_id}/tags/{tag_id}. The `tags` collection is compared as a set on full tag content — array ordering is not significant; differing set membership or differing field values on a matching id returns 400 `invalid_context`. Asset location is not part of the asset resource — it is scan-derived fact data, read through GET /api/v1/reports/asset-locations or GET /api/v1/assets/{asset_id}/history; `location_id` / `location_external_key` in a request body are rejected 400 `read_only`.",
        "operationId": "updateAsset",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/merge-patch+json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateAssetRequest"
              }
            }
          },
          "description": "Fields to merge-patch",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateAssetResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Update an asset",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/api/v1/assets/{asset_id}/history": {
      "get": {
        "description": "**Required scope:** `tracking:read`\n\nLocation history for an asset identified by its canonical id.\n\nEach item is a **stay**: an unbroken run of observations of the asset at one location, not an individual scan. Consecutive observations at the same location are one item; moving away and returning starts a new one. An observation that resolved to no location is its own stay (null `location_id`). History is resolved at one-minute granularity, so a visit shorter than a minute may not appear.\n\n`event_observed_at` is when the stay began. `duration_seconds` runs from there to the first observation of the asset anywhere else, and is null when there has been none since — the stay is ongoing. A stay counts from observation to observation: a period with no reads between two observations at the same location is inside the stay, not a gap in it.\n\n`from` and `to` select which stays are listed — those with at least one observation in the window — but do not clip them. A stay that began before `from` reports its real start, and a stay that continues past `to` reports its real duration. `total_count`, `limit` and `offset` count stays.\n\nThe asset existence check follows path-addressed semantics — the asset is returned even if its `valid_to` has elapsed. Each history row's location reference applies the temporal-validity predicate, so an event referencing a location whose effective window is past surfaces with null `location_external_key`.",
        "operationId": "listAssetHistory",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "RFC 3339 start timestamp",
            "in": "query",
            "name": "from",
            "schema": {
              "example": "2025-04-29T12:34:56.000Z",
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "RFC 3339 end timestamp",
            "in": "query",
            "name": "to",
            "schema": {
              "example": "2025-04-29T12:34:56.000Z",
              "format": "date-time",
              "type": "string"
            }
          },
          {
            "description": "comma-separated; prefix '-' for DESC",
            "explode": false,
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "",
              "pattern": "^(|(?:event_observed_at|-event_observed_at)(?:,(?:event_observed_at|-event_observed_at))*)$",
              "type": "string"
            },
            "style": "form"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetHistoryResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Bad Request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Not Found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Internal Server Error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Asset movement history",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "tracking:read"
        ]
      }
    },
    "/api/v1/assets/{asset_id}/rename": {
      "post": {
        "description": "**Required scope:** `assets:write`\n\nMutate the asset's `external_key` (natural / join key). This operation is **destructive to downstream joins**: any external system that has cached or indexed records on the old `external_key` will silently disconnect. Prefer a coordinated cutover with downstream consumers.\n\n`external_key` is immutable via PATCH; this operation is the only way to change it. Distinct from a regular PATCH in audit logs (different URL surface).\n\nThe response includes `descendant_count_affected` for shape uniformity with the location rename verb. Assets have no hierarchy, so this value is always 0; it is emitted to save typed-client consumers from branching on rename verb.",
        "operationId": "renameAsset",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameAssetRequest"
              }
            }
          },
          "description": "New external_key",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenameAssetResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Rename an asset (mutate external_key)",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/api/v1/assets/{asset_id}/tags": {
      "post": {
        "description": "**Required scope:** `assets:write`\n\nAttach a tag (RFID EPC, BLE beacon ID, barcode, etc.) to an existing asset.\nThe tag must be unique within the organization.",
        "operationId": "addAssetTag",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TagRequest"
              }
            }
          },
          "description": "Tag to attach",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddAssetTagResponse"
                }
              }
            },
            "description": "tag attached",
            "headers": {
              "Location": {
                "description": "Path of the created tag (resolve against request URL per RFC 7231 §7.1.2)",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Add a tag to an asset",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/api/v1/assets/{asset_id}/tags/{tag_id}": {
      "delete": {
        "description": "**Required scope:** `assets:write`\n\nDetach a tag from an asset by its tag record id.\nFirst successful removal returns 204; repeated calls return 404 — consistent with top-level resource DELETE semantics. The cross-asset / cross-org case (a tag that exists but is not attached to this asset, or belongs to a different org) also surfaces as 404.",
        "operationId": "removeAssetTag",
        "parameters": [
          {
            "description": "Asset id (canonical)",
            "in": "path",
            "name": "asset_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Tag id",
            "in": "path",
            "name": "tag_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "deleted",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Remove a tag from an asset",
        "tags": [
          "assets"
        ],
        "x-required-scopes": [
          "assets:write"
        ]
      }
    },
    "/api/v1/locations": {
      "get": {
        "description": "**Required scope:** `locations:read`\n\nPaginated locations list with natural-key filters, sort, and substring search.\n\nDefault scope returns currently-effective locations only — rows whose `valid_from` is in the past AND whose `valid_to` is null or in the future. The `is_active` filter is independent of temporal validity; omit it to include both active and inactive rows within the effective window, or pass `?is_active=true`/`false` to filter further.",
        "operationId": "listLocations",
        "parameters": [
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "filter by parent id (canonical, may repeat); mutually exclusive with parent_external_key (400 ambiguous_fields if both supplied)",
            "explode": true,
            "in": "query",
            "name": "parent_id",
            "schema": {
              "default": [],
              "items": {
                "format": "int64",
                "maximum": 9007199254740991,
                "type": "integer"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by parent's external_key (may repeat); mutually exclusive with parent_id (400 ambiguous_fields if both supplied)",
            "explode": true,
            "in": "query",
            "name": "parent_external_key",
            "schema": {
              "default": [],
              "items": {
                "pattern": "^[A-Za-z0-9-]+$",
                "type": "string"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by location external_key, equality match (may repeat for any-of)",
            "explode": true,
            "in": "query",
            "name": "external_key",
            "schema": {
              "default": [],
              "items": {
                "pattern": "^[A-Za-z0-9-]+$",
                "type": "string"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by active flag",
            "in": "query",
            "name": "is_active",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "description": "when true, include soft-deleted rows in the response. deleted_at is populated for those rows. Orthogonal to is_active.",
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "description": "substring search (case-insensitive) on name, external_key, description, and active tag values",
            "in": "query",
            "name": "q",
            "schema": {
              "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
              "type": "string"
            }
          },
          {
            "description": "comma-separated, prefix '-' for DESC",
            "explode": false,
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "",
              "pattern": "^(|(?:external_key|-external_key|name|-name|created_at|-created_at)(?:,(?:external_key|-external_key|name|-name|created_at|-created_at))*)$",
              "type": "string"
            },
            "style": "form"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListLocationsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List locations",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:read"
        ]
      },
      "post": {
        "description": "**Required scope:** `locations:write`\n\nCreate a new location in the hierarchy, optionally with one or more tags.\nSet parent_id (canonical) or parent_external_key (alternate) to nest under an existing parent.\nBoth forms may be supplied together when they name the same parent (silently normalized to a single re-parent operation); a disagreement returns 400 `ambiguous_fields`.\n\nThe `external_key` field is optional. Provide a value from your system of record\n(ERP, WMS, layout/plan) for natural-key joins, or omit it to receive a\nserver-assigned external_key in the format `LOC-NNN` (per-organization\nsequence, 3-digit zero-pad, grows naturally beyond 999).\nA caller-supplied external_key that collides with an existing location returns 409.",
        "operationId": "createLocation",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateLocationWithTagsRequest"
              }
            }
          },
          "description": "Location to create with optional tags",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreateLocationResponse"
                }
              }
            },
            "description": "Created",
            "headers": {
              "Location": {
                "description": "Path of the created resource (resolve against request URL per RFC 7231 §7.1.2)",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Create a location",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:write"
        ]
      }
    },
    "/api/v1/locations/{location_id}": {
      "delete": {
        "description": "**Required scope:** `locations:write`\n\nDelete a location by its ID. Returns 204 on success, 404 if the location does not exist or has already been deleted, and 409 if the location has descendant locations or assets placed directly at it. Descendants must be reassigned or removed and placed assets must be moved or removed before their parent location can be deleted; bulk cascade is not supported.",
        "operationId": "deleteLocation",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "deleted",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict — has descendants or placed assets",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Delete location",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:write"
        ]
      },
      "get": {
        "description": "**Required scope:** `locations:read`\n\nRetrieve a location by its canonical ID. Returns 404 if not found.\n\nPath-addressed retrieval bypasses the temporal-validity filter applied on list endpoints — any non-deleted location is returned regardless of its `valid_from` / `valid_to` values. Use this endpoint when you have an id and need the row even if its effective window has elapsed.",
        "operationId": "getLocation",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetLocationResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Bad Request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Not Found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Too Many Requests",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get location by ID",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:read"
        ]
      },
      "patch": {
        "description": "**Required scope:** `locations:write`\n\nApply a JSON Merge Patch (RFC 7396) to a location. Only fields included in the request body are changed; fields set to `null` clear the corresponding nullable column. Omitted fields are left unchanged. Every accepted PATCH — empty body (`{}`), verbatim echo of current values, partial mutation, or full mutation — advances `updated_at` on success (filesystem `touch` semantics). Read-only fields are uniformly governed by the accept-if-matches, reject-if-differs rule: a value matching the current resource state is silently normalized out (so a verbatim GET → PATCH round-trip succeeds without manual scrubbing), and a differing value returns 400. The rejection `code` splits the two semantic classes: server-managed fields (`id`, `created_at`, `updated_at`, `deleted_at`) return `code: read_only` — they have no public mutation path. Fields mutable via a sub-resource verb (`external_key`, `tags`) return `code: invalid_context` and the detail names the correct verb: mutate `external_key` via POST /locations/{location_id}/rename; mutate `tags` via POST /locations/{location_id}/tags and DELETE /locations/{location_id}/tags/{tag_id}. The `tags` collection is compared as a set on full tag content — array ordering is not significant; differing set membership or differing field values on a matching id returns 400 `invalid_context`. To re-parent, send `parent_id` (surrogate) OR `parent_external_key` (natural key), or both forms in the same body provided they resolve to the same parent (silently normalized to a single re-parent operation, symmetric with CreateLocationRequest); either form accepts `null` to clear the FK, and disagreement between the two forms returns 400 `ambiguous_fields`.",
        "operationId": "updateLocation",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/merge-patch+json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateLocationRequest"
              }
            }
          },
          "description": "Fields to merge-patch",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UpdateLocationResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Update a location",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:write"
        ]
      }
    },
    "/api/v1/locations/{location_id}/ancestors": {
      "get": {
        "description": "**Required scope:** `locations:read`\n\nSort order is fixed: ancestors are returned root first (walking up the `parent_id` chain), with `id` ascending as a deterministic tiebreaker. No `sort` query parameter is exposed because the natural order toward the root is the only meaningful order for this list.",
        "operationId": "listLocationAncestors",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListLocationAncestorsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List location ancestors",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:read"
        ]
      }
    },
    "/api/v1/locations/{location_id}/children": {
      "get": {
        "description": "**Required scope:** `locations:read`\n\nSort order is fixed: immediate children are returned ordered alphabetically by `name` ascending, with `id` ascending as a deterministic tiebreaker when sibling names collide. No `sort` query parameter is exposed because alphabetical-by-name is the only meaningful order for a single level of siblings.",
        "operationId": "listLocationChildren",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListLocationChildrenResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List location children",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:read"
        ]
      }
    },
    "/api/v1/locations/{location_id}/descendants": {
      "get": {
        "description": "**Required scope:** `locations:read`\n\nSort order is fixed: descendants are returned in depth-first tree order (each level sorted by lowercased `external_key`), with `id` ascending as a deterministic tiebreaker. No `sort` query parameter is exposed because the depth-first tree walk is the only meaningful order for this list.",
        "operationId": "listLocationDescendants",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ListLocationDescendantsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List location descendants",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:read"
        ]
      }
    },
    "/api/v1/locations/{location_id}/rename": {
      "post": {
        "description": "**Required scope:** `locations:write`\n\nMutate the location's `external_key`. This operation is **destructive to downstream joins** because consumers of the natural key must re-resolve it. Only this row's `external_key` changes on the server; descendants are not modified.\n\nThe response includes `descendant_count_affected` (the live descendant count reachable through `parent_id`) so an integrator can decide whether to refresh derived natural-key joins for the subtree. `external_key` is immutable via PATCH; this operation is the only way to change it. Distinct from a regular PATCH in audit logs (different URL surface).",
        "operationId": "renameLocation",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RenameLocationRequest"
              }
            }
          },
          "description": "New external_key",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RenameLocationResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Rename a location (mutate external_key)",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:write"
        ]
      }
    },
    "/api/v1/locations/{location_id}/tags": {
      "post": {
        "description": "**Required scope:** `locations:write`",
        "operationId": "addLocationTag",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TagRequest"
              }
            }
          },
          "description": "Tag to attach",
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AddLocationTagResponse"
                }
              }
            },
            "description": "tag attached",
            "headers": {
              "Location": {
                "description": "Path of the created tag (resolve against request URL per RFC 7231 §7.1.2)",
                "schema": {
                  "type": "string"
                }
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "409": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "conflict",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Add a tag to a location",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:write"
        ]
      }
    },
    "/api/v1/locations/{location_id}/tags/{tag_id}": {
      "delete": {
        "description": "**Required scope:** `locations:write`\n\nDetach a tag from a location by its tag record id.\nFirst successful removal returns 204; repeated calls return 404 — consistent with top-level resource DELETE semantics. The cross-location / cross-org case (a tag that exists but is not attached to this location, or belongs to a different org) also surfaces as 404.",
        "operationId": "removeLocationTag",
        "parameters": [
          {
            "description": "Location ID",
            "in": "path",
            "name": "location_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "Tag ID",
            "in": "path",
            "name": "tag_id",
            "required": true,
            "schema": {
              "format": "int64",
              "maximum": 9007199254740991,
              "minimum": 1,
              "type": "integer"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "deleted",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "internal_error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Remove a tag from a location",
        "tags": [
          "locations"
        ],
        "x-required-scopes": [
          "locations:write"
        ]
      }
    },
    "/api/v1/oauth/token": {
      "post": {
        "description": "Exchange API credentials for a short-lived (15 min) access token + a rotating 30-day refresh token. Two grants are supported. `client_credentials`: supply `client_id` and `client_secret` (the opaque {client_id, client_secret} pair returned once at API-key creation). `refresh_token`: supply a current `refresh_token` to rotate the pair; presenting an already-used refresh token revokes the whole chain and returns 401.",
        "operationId": "createToken",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            },
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/TokenRequest"
              }
            }
          },
          "description": "Token grant request",
          "required": true
        },
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Validation error / unsupported grant_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Invalid client credentials or refresh token",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "415": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "unsupported_media_type",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "summary": "OAuth2 token grant",
        "tags": [
          "oauth"
        ],
        "x-required-scopes": []
      }
    },
    "/api/v1/orgs/me": {
      "get": {
        "description": "Returns the organization scoped by the API key presented in Authorization. Intended as a lightweight health-check primitive for integrators verifying a key works end-to-end. Singleton endpoint; accepts no query parameters. Any query parameter returns `400 validation_error / unknown_field`.",
        "operationId": "getCurrentOrg",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GetCurrentOrgResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "bad_request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "not_found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "missing_org_context — the API key authenticated but its org no longer exists",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Internal server error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "Get the org associated with the authenticated API key",
        "tags": [
          "orgs"
        ],
        "x-required-scopes": []
      }
    },
    "/api/v1/reports/asset-locations": {
      "get": {
        "description": "**Required scope:** `tracking:read`\n\nSnapshot of each asset's most recent location, filterable by either side of the join. Filter by location (`location_id` / `location_external_key`) to retrieve everything currently at a place; filter by asset (`asset_id` / `asset_external_key`, repeatable) to resolve a batch of assets from a master system to their current locations in one round-trip. Within each pair the surrogate and natural-key forms are mutually exclusive (400 `ambiguous_fields` if both are supplied); the asset and location filter pairs are independent and intersect when combined. Because this view is derived from immutable scan history, it can resolve references for assets that have since been deleted. By default those rows are excluded; pass `include_deleted=true` to include them, and check `asset_deleted_at` to distinguish deleted from live.\n\nRows are produced from `scan_event` history and reflect the most recent observed location per asset. **Assets that have never been scanned do not appear in this report** — they exist in `/api/v1/assets` but have no derived location row until at least one scan event has been observed, so this endpoint's `total_count` can lag `/api/v1/assets` `total_count` for newly-onboarded inventory. Use `/api/v1/assets` directly if you need a complete asset roster including never-scanned assets.\n\n\nEach row also carries the asset's current **dwell** — how long it has been at `location_id` without moving. `dwell_started_at` is the first observation of the asset at that location within its current unbroken run (a change of location starts a new run; a scan that resolved to no location also ends the previous one). `dwell_seconds` is `asset_last_seen - dwell_started_at`.\n\nDwell is an **observed span, not a wall clock**: it is measured to `asset_last_seen`, so it stops growing once the asset stops being read rather than continuing to climb for an asset that has left. To decide whether a dwell is still current, compare `asset_last_seen` against your own staleness threshold. Both fields are always present. Dwell is derived from scan history at one-minute resolution and is reported conservatively — `dwell_started_at` is never earlier than the moment the asset was confirmed at that location. It reflects the underlying scan history, so it is still reported on rows whose `location_id` has been nulled out by soft-deletion or temporal validity.\n\nTemporal validity is applied to both joined entities. Assets whose effective window is past or future are excluded entirely. Locations whose effective window is past or future surface with null `location_id` / `location_external_key` while the parent asset row remains visible. Soft-deleted locations are projected the same way here — null on the report row — even though the identifier still lives on the location row; reports endpoints intentionally hide tombstoned anchor points from scan-derived summaries. Use the locations endpoint with `include_deleted=true` to retrieve the underlying identifier.",
        "operationId": "listAssetLocations",
        "parameters": [
          {
            "description": "max 200",
            "in": "query",
            "name": "limit",
            "schema": {
              "default": 50,
              "maximum": 200,
              "minimum": 1,
              "type": "integer"
            }
          },
          {
            "description": "min 0",
            "in": "query",
            "name": "offset",
            "schema": {
              "default": 0,
              "maximum": 2147483647,
              "minimum": 0,
              "type": "integer"
            }
          },
          {
            "description": "filter by location id (canonical, may repeat); mutually exclusive with location_external_key (400 ambiguous_fields if both supplied)",
            "explode": true,
            "in": "query",
            "name": "location_id",
            "schema": {
              "default": [],
              "items": {
                "format": "int64",
                "maximum": 9007199254740991,
                "type": "integer"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by location external_key (may repeat); mutually exclusive with location_id (400 ambiguous_fields if both supplied)",
            "explode": true,
            "in": "query",
            "name": "location_external_key",
            "schema": {
              "default": [],
              "items": {
                "pattern": "^[A-Za-z0-9-]+$",
                "type": "string"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by asset id (canonical, may repeat); mutually exclusive with asset_external_key (400 ambiguous_fields if both supplied)",
            "explode": true,
            "in": "query",
            "name": "asset_id",
            "schema": {
              "default": [],
              "items": {
                "format": "int64",
                "maximum": 9007199254740991,
                "type": "integer"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "filter by asset external_key (may repeat); mutually exclusive with asset_id (400 ambiguous_fields if both supplied)",
            "explode": true,
            "in": "query",
            "name": "asset_external_key",
            "schema": {
              "default": [],
              "items": {
                "pattern": "^[A-Za-z0-9-]+$",
                "type": "string"
              },
              "type": "array"
            },
            "style": "form"
          },
          {
            "description": "substring search (case-insensitive) on asset name, external_key, and active tag values",
            "in": "query",
            "name": "q",
            "schema": {
              "pattern": "^[^\\x00-\\x08\\x0B\\x0C\\x0E-\\x1F\\x7F]*$",
              "type": "string"
            }
          },
          {
            "description": "include rows for soft-deleted assets",
            "in": "query",
            "name": "include_deleted",
            "schema": {
              "default": false,
              "type": "boolean"
            }
          },
          {
            "description": "comma-separated sort fields; prefix '-' for DESC",
            "explode": false,
            "in": "query",
            "name": "sort",
            "schema": {
              "default": "",
              "pattern": "^(|(?:asset_last_seen|-asset_last_seen|asset_external_key|-asset_external_key|location_external_key|-location_external_key)(?:,(?:asset_last_seen|-asset_last_seen|asset_external_key|-asset_external_key|location_external_key|-location_external_key))*)$",
              "type": "string"
            },
            "style": "form"
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AssetLocationsResponse"
                }
              }
            },
            "description": "OK",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Bad Request",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "401": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unauthorized",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WWWAuthenticate"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "403": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Forbidden",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "404": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Not Found",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "405": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Method not allowed",
            "headers": {
              "Allow": {
                "$ref": "#/components/headers/Allow"
              },
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "429": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "rate_limited",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Internal Server Error",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "default": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            },
            "description": "Unmodeled error. Generated clients should treat any response not otherwise enumerated as a structured ErrorResponse.",
            "headers": {
              "RateLimit-Policy": {
                "$ref": "#/components/headers/RateLimitPolicy"
              },
              "X-RateLimit-Limit": {
                "$ref": "#/components/headers/XRateLimitLimit"
              },
              "X-RateLimit-Remaining": {
                "$ref": "#/components/headers/XRateLimitRemaining"
              },
              "X-RateLimit-Reset": {
                "$ref": "#/components/headers/XRateLimitReset"
              },
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          }
        },
        "security": [
          {
            "BearerAuth": []
          }
        ],
        "summary": "List current asset locations",
        "tags": [
          "reports"
        ],
        "x-required-scopes": [
          "tracking:read"
        ]
      }
    }
  },
  "security": [
    {
      "BearerAuth": []
    }
  ],
  "servers": [
    {
      "description": "Preview (per-PR deploys). Preview-scoped API keys authenticate here only — they will fail with 401 against Production, and Production keys will fail here.",
      "url": "https://app.preview.trakrf.id"
    },
    {
      "description": "Production. Production-scoped API keys authenticate here only — they will fail with 401 against Preview, and Preview keys will fail here.",
      "url": "https://app.trakrf.id"
    }
  ],
  "tags": [
    {
      "description": "Asset CRUD, history, and tag membership.",
      "name": "assets"
    },
    {
      "description": "Location CRUD, hierarchy traversal, and tag membership.",
      "name": "locations"
    },
    {
      "description": "Caller's organization context.",
      "name": "orgs"
    },
    {
      "description": "Cross-cutting reporting endpoints (asset locations, etc.).",
      "name": "reports"
    }
  ]
}