{
  "info": {
    "name": "OutReserve Supply API v1",
    "description": "# OutReserve Supply API — developer quickstart\n\nCreate and manage **properties, units, images, prices and availability** through the private content/ARI preview.\n\n> **Release boundary:** this collection does not activate reservations, publish listings, or establish a public sandbox. Reservation pull/ack remains a separate, uncertified preview. There are no DELETE operations.\n\n## 1. Configure an authorized environment\n\nImport the companion environment and duplicate it for your account. Store the Supply Bearer credential in **Local Vault**, restrict its allowed domain to the authorized API host, and set `apiKey` to a reference such as `{{vault:your-supply-key}}`. Never paste the real key into a shared environment or export it. Use an expiring, least-privilege `supply:read`/`supply:write` credential; content/ARI testing needs no reservation scopes.\n\n| Variable | What to supply |\n| --- | --- |\n| `baseUrl` | Authorized API prefix, ending in `/api/v1/supply`; no trailing slash |\n| `apiKey` | Dedicated Supply credential, not a consumer Developer API key |\n| `countryCode`, `stateCode`, `destinationSlug` | Exact catalog values, not assumed ISO spelling; `USA` may be returned instead of `US` |\n| `externalPropertyId`, `propertyName`, `propertyTimezone` | Unique partner ID, test name and explicit IANA timezone |\n| `externalPhysicalUnitId`, `externalPooledUnitId` | Unique partner inventory IDs; never double-count stock |\n| `dateFrom`, `dateTo` | Future property-local dates, inclusive for ARI |\n\n## 2. Follow the workflow\n\n1. **Connection:** inspect granted permissions and account approval.\n2. **Discovery:** choose locations and writable amenities; follow pagination.\n3. **Onboarding:** create a pending property, create physical/pooled units, and update/read back metadata.\n4. **Optional media:** supply a real permitted HTTPS image, then poll media and operation state.\n5. **Operator checkpoint:** submit for review and pause for OutReserve approval. Submission cannot approve itself.\n6. **Calendar ARI:** read the revision, apply dated rates/counts/closures, then read back each affected unit/day.\n7. **Diagnostics:** inspect request outcomes and field audits without exposing credentials or guest data.\n\n**Do not run the entire collection unattended.** Existing-property association is an alternative to creation, image processing is asynchronous, and approval is an operator step. Requests may need different environment values.\n\n## 3. Prices, inventory and safe retries\n\n- Money uses integer currency minor units: `18500` means USD 185.00. Price precedence is unit/date → property/date → unit default → property default. Defaults do not create inventory.\n- Counts are **absolute net inventory**, not deltas. A closure does not erase a reported count. Zero effective sellability is expected before separate reservation certification/activation.\n- Onboarding POST keys persist per named request. ARI also preserves its original quoted `If-Match` revision alongside its key.\n- After a timeout, keep the **same method, path, exact body, key and saved precondition**. Read back/audit before deciding whether it committed. Never mint a new key merely because the outcome is unknown.\n- After a confirmed/reconciled outcome, clear only that request's saved key before a genuinely different write. ARI readback does not clear retry state.\n\n## 4. Problems and further examples\n\nErrors use `application/problem+json`. Inspect `code`, `status`, field pointer, `retryable`, recovery context and request ID; honor `Retry-After` when present. A `412 stale_revision` requires readback and deliberate reconciliation, not automatic replay with a new revision.\n\nRepository documentation: `docs/api/supply/integration-testing.md` (full acceptance walkthrough, default/date prices and property/unit closures), `docs/api/supply/openapi-v1.yaml` (contract), `docs/api/supply/errors.md` and `endpoint-error-matrix.md` (error reference). The checkout-local NPX toolkit remains unpublished.\n\nOnline guides: [acceptance walkthrough](https://outreserve.com/developers/supply/integration-testing.md), [error codes](https://outreserve.com/developers/supply/errors.md), and [agent documentation index](https://outreserve.com/developers/supply/llms.txt). Reservation protocol downloads remain operator-only; neither this collection nor the offline toolkit grants certification.\n",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [{ "key": "token", "value": "{{apiKey}}", "type": "string" }]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "const onboardingKeyNames = {",
          "  'Create pending property': 'createPropertyKey',",
          "  'Create physical unit': 'createPhysicalUnitKey',",
          "  'Create pooled unit': 'createPooledUnitKey',",
          "  'Request existing property association': 'connectPropertyKey',",
          "  'Submit property for review': 'submitPropertyKey',",
          "  'Import property image': 'importMediaKey'",
          "};",
          "const keyName = onboardingKeyNames[pm.info.requestName];",
          "if (keyName) {",
          "  if (!pm.environment.get(keyName)) pm.environment.set(keyName, pm.variables.replaceIn('{{$guid}}'));",
          "  pm.request.headers.upsert({ key: 'Idempotency-Key', value: pm.environment.get(keyName) });",
          "}"
        ]
      }
    },
    {
      "listen": "test",
      "script": {
        "type": "text/javascript",
        "exec": [
          "if (pm.response.code >= 400 && pm.response.headers.get('Content-Type')?.includes('application/problem+json')) {",
          "  const problem = pm.response.json();",
          "  pm.test('Error has stable Supply code and request ID', function () {",
          "    pm.expect(problem.code).to.be.a('string');",
          "    pm.expect(problem.code).to.match(/^[a-z][a-z0-9_]*$/);",
          "    pm.expect(problem.type).to.equal(`https://outreserve.com/developers/supply/errors/${problem.code}`);",
          "    pm.expect(problem.title).to.be.a('string');",
          "    pm.expect(problem.detail).to.be.a('string');",
          "    pm.expect(problem.status).to.equal(pm.response.code);",
          "    pm.expect(problem.request_id).to.be.a('string');",
          "    pm.expect(problem.request_id).to.equal(pm.response.headers.get('X-Request-Id'));",
          "    pm.expect(problem.retryable).to.equal(pm.response.code === 429 || pm.response.code >= 500);",
          "  });",
          "  const recoveryFields = {",
          "    stale_revision: ['current_revision', 'submitted_revision'],",
          "    reservation_watermark_ahead: ['applied_reservation_sequence', 'submitted_sequence'],",
          "    reservation_watermark_regression: ['current_incorporated_sequence', 'submitted_sequence']",
          "  }[problem.code];",
          "  if (recoveryFields) pm.test('Conflict has numeric recovery context', function () {",
          "    pm.expect(Object.keys(problem.context).sort()).to.deep.equal(recoveryFields.sort());",
          "    recoveryFields.forEach(field => pm.expect(problem.context[field]).to.be.a('number'));",
          "  });",
          "}"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "01 Connection",
      "description": "## Connection\n\nConfirm this credential's account, scopes, approval and booking-readiness flags before writing. A valid credential is not proof of property approval.",
      "item": [
        {
          "name": "Get connection",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/connection",
            "description": "## Get connection\n\nInspect account-scoped approval, permissions, and bookability before importing content.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Connection response', function () { pm.response.to.have.status(200); });",
            "if (pm.response.code === 200) pm.environment.set('connectionId', pm.response.json().data.id);"
          ] } }]
        }
      ]
    },
    {
      "name": "01a Amenity discovery",
      "description": "## Amenity discovery\n\nDiscover canonical property amenity IDs. Only writable entries can be assigned. Follow `meta.has_more`; PATCH sends the complete desired amenity set, with omission meaning unchanged and `[]` meaning clear.",
      "item": [
        {
          "name": "List property amenities",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/amenities?per_page=50&page=1",
            "description": "## List property amenities\n\nDiscover canonical numeric property amenity IDs before sending property.amenity_ids. Follow meta.has_more; only writable=true entries can be assigned by Supply v1.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Amenity catalog', function () { pm.response.to.have.status(200); });"
          ] } }]
        }
      ]
    },
    {
      "name": "01b Location discovery",
      "description": "## Location discovery\n\nRun countries → states → destinations. Manually select the intended geography and save its exact identifiers. Do not automatically use the first result; catalogs may include locations with no consumer listings.",
      "item": [
        {
          "name": "List countries",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/locations?level=countries",
            "description": "## List countries\n\nSelect the intended country_code from data; set countryCode manually before listing states. This includes zero-property geographies.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Country catalog', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "List states",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/locations?level=states&country_code={{countryCode}}",
            "description": "## List states\n\nSelect the intended state_code from data; set stateCode manually before listing destinations.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Copy the exact `country_code` returned by country discovery; do not assume `US` if the catalog returns `USA`.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('State catalog', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "List destinations",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/locations?level=destinations&country_code={{countryCode}}&state_code={{stateCode}}&per_page=50&page=1",
            "description": "## List destinations\n\nSelect the intended destination_slug from data; set destinationSlug manually. Follow meta.has_more with the next page until false. Do not select the first result automatically.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Copy the exact `country_code` returned by country discovery; do not assume `US` if the catalog returns `USA`.\n- Copy the exact `state_code` returned under the selected country.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Destination catalog', function () { pm.response.to.have.status(200); });"
          ] } }]
        }
      ]
    },
    {
      "name": "02 Property onboarding",
      "description": "## Property onboarding\n\nCreate pending supply and read it back before review. Physical and pooled units represent different stock models; capacity is inventory, not guest occupancy.\n\n> **Manual checkpoints:** existing-property association is an alternative workflow, not the next step after creation. Images require async polling. Submission requires separate OutReserve operator approval before ARI writes. Approval does not activate reservations.",
      "item": [
        {
          "name": "List properties",
          "request": { "description": "## List properties\n\nList properties mapped to this Supply connection; use returned UUIDs for subsequent requests.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "GET", "url": "{{baseUrl}}/properties" },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Property list', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Create pending property",
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"property\": {\n    \"external_property_id\": \"{{externalPropertyId}}\",\n    \"name\": \"{{propertyName}}\",\n    \"currency\": \"USD\",\n    \"country_code\": \"{{countryCode}}\",\n    \"state_code\": \"{{stateCode}}\",\n    \"destination_slug\": \"{{destinationSlug}}\",\n    \"timezone\": \"{{propertyTimezone}}\"\n  }\n}" },
            "description": "## Create pending property\n\nFirst select exact countryCode, stateCode, and destinationSlug from the Supply location catalog. Creation does not activate bookability.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Copy the exact `country_code` returned by country discovery; do not assume `US` if the catalog returns `USA`.\n- Copy the exact `state_code` returned under the selected country.\n\n### Expected result\n\nExpect **`201`**. Check the response data and saved environment variables before continuing. Creation remains staged/non-bookable; retain the returned UUID.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"property\": {\n    \"external_property_id\": \"{{externalPropertyId}}\",\n    \"name\": \"{{propertyName}}\",\n    \"currency\": \"USD\",\n    \"country_code\": \"{{countryCode}}\",\n    \"state_code\": \"{{stateCode}}\",\n    \"destination_slug\": \"{{destinationSlug}}\",\n    \"timezone\": \"{{propertyTimezone}}\"\n  }\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Property staged', function () { pm.response.to.have.status(201); });",
            "if (pm.response.code === 201) pm.environment.set('propertyId', pm.response.json().data.id);"
          ] } }]
        },
        {
          "name": "Get property",
          "request": { "description": "## Get property\n\nRead the staged or approved property, its partner mapping and readiness state. Verify prior changes by readback.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "GET", "url": "{{baseUrl}}/properties/{{propertyId}}" },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Property response', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Update property content",
          "request": {
            "method": "PATCH",
            "description": "## Update property content\n\nUpdate only allowed mutable property fields. This example changes the description; it does not approve or activate the listing.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"property\": {\n    \"description\": \"Operator managed camping and cabins.\"\n  }\n}\n```\n\n### Retries and errors\n\nRead back before retrying an uncertain PATCH. Omitted fields remain unchanged; changing status never physically deletes history.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.",
            "url": "{{baseUrl}}/properties/{{propertyId}}",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"property\": {\n    \"description\": \"Operator managed camping and cabins.\"\n  }\n}" }
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Property updated', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "List units",
          "request": { "description": "## List units\n\nList physical and pooled inventory products attached to the selected property.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "GET", "url": "{{baseUrl}}/properties/{{propertyId}}/units" },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Unit list', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Create physical unit",
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties/{{propertyId}}/units",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"unit\": {\n    \"external_unit_id\": \"{{externalPhysicalUnitId}}\",\n    \"name\": \"Site A12\",\n    \"unit_type\": \"RV\",\n    \"inventory_mode\": \"physical\",\n    \"capacity\": 1\n  }\n}" },
            "description": "## Create physical unit\n\nConfirm the unit type and its required typed fields against capabilities before sending.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`201`**. Check the response data and saved environment variables before continuing. Creation remains staged/non-bookable; retain the returned UUID.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"unit\": {\n    \"external_unit_id\": \"{{externalPhysicalUnitId}}\",\n    \"name\": \"Site A12\",\n    \"unit_type\": \"RV\",\n    \"inventory_mode\": \"physical\",\n    \"capacity\": 1\n  }\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Physical unit created', function () { pm.response.to.have.status(201); });",
            "if (pm.response.code === 201) pm.environment.set('unitId', pm.response.json().data.id);"
          ] } }]
        },
        {
          "name": "Create pooled unit",
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties/{{propertyId}}/units",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"unit\": {\n    \"external_unit_id\": \"{{externalPooledUnitId}}\",\n    \"name\": \"Standard cabins\",\n    \"unit_type\": \"Cabin\",\n    \"inventory_mode\": \"pooled\",\n    \"capacity\": 6\n  }\n}" },
            "description": "## Create pooled unit\n\nUse only for interchangeable stock, never the same physical stock sold through individual units.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`201`**. Check the response data and saved environment variables before continuing. Creation remains staged/non-bookable; retain the returned UUID.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"unit\": {\n    \"external_unit_id\": \"{{externalPooledUnitId}}\",\n    \"name\": \"Standard cabins\",\n    \"unit_type\": \"Cabin\",\n    \"inventory_mode\": \"pooled\",\n    \"capacity\": 6\n  }\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Pool created', function () { pm.response.to.have.status(201); });",
            "if (pm.response.code === 201) pm.environment.set('poolUnitId', pm.response.json().data.id);"
          ] } }]
        },
        {
          "name": "Get unit",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/properties/{{propertyId}}/units/{{unitId}}",
            "description": "## Get unit\n\nRead the selected physical unit's typed metadata and booking readiness before editing it.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `unitId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Unit response', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Update unit metadata",
          "request": {
            "method": "PATCH",
            "url": "{{baseUrl}}/properties/{{propertyId}}/units/{{unitId}}",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"unit\": {\n    \"name\": \"Site A12 - shaded\"\n  }\n}" },
            "description": "## Update unit metadata\n\nPatch only mutable typed fields. To deactivate without deleting history, send status inactive as a separate reviewed change.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `unitId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"unit\": {\n    \"name\": \"Site A12 - shaded\"\n  }\n}\n```\n\n### Retries and errors\n\nRead back before retrying an uncertain PATCH. Omitted fields remain unchanged; changing status never physically deletes history.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Unit updated', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Request existing property association",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Existing property association staged', function () { pm.response.to.have.status(201); });",
            "if (pm.response.code === 201) pm.test('Association remains pending review', function () { pm.expect(pm.response.json().data.id).to.equal(pm.environment.get('existingPropertyId')); pm.expect(pm.response.json().data.approval_status).to.equal('pending'); });"
          ] } }],
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties/{{existingPropertyId}}/connect",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"connection_request\": {\n    \"external_property_id\": \"{{externalPropertyId}}\"\n  }\n}" },
            "description": "## Request existing property association\n\nSeparate adoption flow for an existing OutReserve UUID. Requires OutReserve review; do not use after creating a new property with the same external ID.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `existingPropertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`201`** with a pending association for the existing property. This does not grant control; pause for OutReserve review before managing this property.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"connection_request\": {\n    \"external_property_id\": \"{{externalPropertyId}}\"\n  }\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          }
        },
        {
          "name": "Submit property for review",
          "request": { "description": "## Submit property for review\n\nRequest OutReserve review of the staged property. Stop here for operator approval before attempting ARI.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`202`**. Check the response data and saved environment variables before continuing. **Pause for OutReserve approval.** This does not approve or publish the property.\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "POST", "url": "{{baseUrl}}/properties/{{propertyId}}/submit" },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Review submission accepted', function () { pm.response.to.have.status(202); });"
          ] } }]
        },
        {
          "name": "Import property image",
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties/{{propertyId}}/media",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"media\": {\n    \"source_url\": \"{{publicImageUrl}}\",\n    \"alt_text\": \"Cabin exterior\",\n    \"featured\": true\n  }\n}" },
            "description": "## Import property image\n\nPublic HTTPS source only. 202 means queued; inspect operation/media processing state before considering it ready. The collection persists importMediaKey for exact retries. Keep the same raw body, path, and key after a timeout; clear importMediaKey only for a new logical import. A changed signed URL requires a new key after reconciliation.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`202`**. Check the response data and saved environment variables before continuing. `202` means queued, not ready; use the returned `mediaId` and `operationId` to poll.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"media\": {\n    \"source_url\": \"{{publicImageUrl}}\",\n    \"alt_text\": \"Cabin exterior\",\n    \"featured\": true\n  }\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Media import queued', function () { pm.response.to.have.status(202); });",
            "if (pm.response.code === 202) { pm.environment.set('mediaId', pm.response.json().data.id); pm.environment.set('operationId', pm.response.json().meta.operation_id); }"
          ] } }]
        },
        {
          "name": "Check media processing",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Media status response', function () { pm.response.to.have.status(200); });",
            "if (pm.response.code === 200) {",
            "  const data = pm.response.json().data;",
            "  pm.test('Media identity and processing state', function () { pm.expect(data.id).to.equal(pm.environment.get('mediaId')); pm.expect(['pending', 'ready', 'failed']).to.include(data.processing_status); });",
            "  pm.test('Media has no terminal import failure', function () { pm.expect(data.processing_status).to.not.equal('failed'); });",
            "  if (data.processing_status === 'ready') pm.test('Ready media has an image URL', function () { pm.expect(data.image_url).to.be.a('string'); });",
            "}"
          ] } }],
          "request": { "description": "## Check media processing\n\nInspect the imported image's processing state. Poll until a terminal result; a queued response is not import success.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `mediaId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Inspect the response data against the OpenAPI contract. Pending/running work is not terminal success; a failed operation is a failed test.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "GET", "url": "{{baseUrl}}/properties/{{propertyId}}/media/{{mediaId}}" }
        },
        {
          "name": "List media",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/properties/{{propertyId}}/media",
            "description": "## List media\n\nList property and unit images with their current import state.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Media list', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Update media metadata",
          "request": {
            "method": "PATCH",
            "url": "{{baseUrl}}/properties/{{propertyId}}/media/{{mediaId}}",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": { "mode": "raw", "raw": "{\n  \"media\": {\n    \"alt_text\": \"Cabin exterior from the path\"\n  }\n}" },
            "description": "## Update media metadata\n\nEdit metadata without changing the source URL or owner. Send status deleted only when intentionally deactivating this media record; no DELETE endpoint exists.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `mediaId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"media\": {\n    \"alt_text\": \"Cabin exterior from the path\"\n  }\n}\n```\n\n### Retries and errors\n\nRead back before retrying an uncertain PATCH. Omitted fields remain unchanged; changing status never physically deletes history.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Media updated', function () { pm.response.to.have.status(200); });"
          ] } }]
        }
      ]
    },
    {
      "name": "03 Calendar ARI",
      "description": "## Calendar ARI\n\n**Prerequisites:** approved mapping, created unit UUIDs, future inclusive dates and write permissions.\n\nRead ARI first. Writes require a retained `Idempotency-Key` and quoted `If-Match`. Report absolute net counts and verify rates, closures, revisions and inventory independently. Do not confuse reported stock with effective sellability.\n\nFor default pricing, property-wide dated prices, single-date overrides and property/unit closures, use the payload variations in `docs/api/supply/integration-testing.md`.",
      "item": [
        {
          "name": "Read ARI and capture revision",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/properties/{{propertyId}}/ari?date_from={{dateFrom}}&date_to={{dateTo}}",
            "description": "## Read ARI and capture revision\n\nInspect source values, effective sellability, and calendar revision.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `dateFrom` to a future property-local `YYYY-MM-DD` date; ARI ranges include both endpoints.\n- Set `dateTo` to the final inclusive property-local `YYYY-MM-DD` date, on or after `dateFrom`.\n- For writes, wait for operator approval and read the current calendar revision first.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('ARI readback', function () { pm.response.to.have.status(200); });",
            "if (pm.response.code === 200) pm.environment.set('calendarRevision', pm.response.json().data.calendar_revision);"
          ] } }]
        },
        {
          "name": "Apply physical unit ARI",
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties/{{propertyId}}/ari",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "If-Match", "value": "\"{{physicalIfMatch}}\"" },
              { "key": "Idempotency-Key", "value": "{{idempotencyKey}}" }
            ],
            "body": { "mode": "raw", "raw": "{\n  \"updates\": [{\n    \"scope\": \"unit\",\n    \"unit_id\": \"{{unitId}}\",\n    \"date_from\": \"{{dateFrom}}\",\n    \"date_to\": \"{{dateTo}}\",\n    \"available_count\": 1,\n    \"incorporated_reservation_sequence\": {{incorporatedReservationSequence}},\n    \"rate_minor\": 18500,\n    \"stop_sell\": false\n  }]\n}" },
            "description": "## Apply physical unit ARI\n\nRun Read ARI first. This request saves physicalIfMatch when it first creates idempotencyKey. Keep the same key, body, and saved precondition on an exact retry; after a confirmed or reconciled outcome, manually clear idempotencyKey before a different write.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `unitId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `dateFrom` to a future property-local `YYYY-MM-DD` date; ARI ranges include both endpoints.\n- Set `dateTo` to the final inclusive property-local `YYYY-MM-DD` date, on or after `dateFrom`.\n- For writes, wait for operator approval and read the current calendar revision first.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"updates\": [{\n    \"scope\": \"unit\",\n    \"unit_id\": \"{{unitId}}\",\n    \"date_from\": \"{{dateFrom}}\",\n    \"date_to\": \"{{dateTo}}\",\n    \"available_count\": 1,\n    \"incorporated_reservation_sequence\": {{incorporatedReservationSequence}},\n    \"rate_minor\": 18500,\n    \"stop_sell\": false\n  }]\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [
            { "listen": "prerequest", "script": { "type": "text/javascript", "exec": [
              "if (!pm.environment.get('idempotencyKey')) {",
              "  const revision = String(pm.environment.get('calendarRevision') ?? '');",
              "  if (!/^(0|[1-9]\\d*)$/.test(revision)) throw new Error('Read ARI before starting a new physical Unit write');",
              "  pm.environment.set('physicalIfMatch', revision);",
              "  pm.environment.set('idempotencyKey', pm.variables.replaceIn('{{$guid}}'));",
              "}",
              "if (!pm.environment.get('physicalIfMatch')) throw new Error('Saved physicalIfMatch is missing; reconcile before retrying');"
            ] } },
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('Atomic ARI applied', function () { pm.response.to.have.status(200); });",
              "if (pm.response.code === 200) pm.environment.set('calendarRevision', pm.response.json().data.calendar_revision);"
            ] } }
          ]
        },
        {
          "name": "Apply pool count and closure",
          "request": {
            "method": "POST",
            "url": "{{baseUrl}}/properties/{{propertyId}}/ari",
            "header": [
              { "key": "Content-Type", "value": "application/json" },
              { "key": "If-Match", "value": "\"{{poolIfMatch}}\"" },
              { "key": "Idempotency-Key", "value": "{{poolIdempotencyKey}}" }
            ],
            "body": { "mode": "raw", "raw": "{\n  \"updates\": [{\n    \"scope\": \"unit\",\n    \"unit_id\": \"{{poolUnitId}}\",\n    \"date_from\": \"{{dateFrom}}\",\n    \"date_to\": \"{{dateTo}}\",\n    \"available_count\": 4,\n    \"incorporated_reservation_sequence\": {{incorporatedReservationSequence}},\n    \"stop_sell\": true\n  }]\n}" },
            "description": "## Apply pool count and closure\n\nA stop sell keeps the reported count at four. This request persists its own key and poolIfMatch; retain both and the body for an exact retry.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `poolUnitId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `dateFrom` to a future property-local `YYYY-MM-DD` date; ARI ranges include both endpoints.\n- Set `dateTo` to the final inclusive property-local `YYYY-MM-DD` date, on or after `dateFrom`.\n- For writes, wait for operator approval and read the current calendar revision first.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Example payload\n\nThe Body tab contains this editable template. Resolve the environment variables before sending.\n\n```json\n{\n  \"updates\": [{\n    \"scope\": \"unit\",\n    \"unit_id\": \"{{poolUnitId}}\",\n    \"date_from\": \"{{dateFrom}}\",\n    \"date_to\": \"{{dateTo}}\",\n    \"available_count\": 4,\n    \"incorporated_reservation_sequence\": {{incorporatedReservationSequence}},\n    \"stop_sell\": true\n  }]\n}\n```\n\n### Retries and errors\n\nPreserve the request's saved idempotency key and exact body/path after an unknown outcome. For ARI, also preserve its saved `If-Match`. Reconcile through readback/audit before clearing a key for a different operation.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [
            { "listen": "prerequest", "script": { "type": "text/javascript", "exec": [
              "if (!pm.environment.get('poolIdempotencyKey')) {",
              "  const revision = String(pm.environment.get('calendarRevision') ?? '');",
              "  if (!/^(0|[1-9]\\d*)$/.test(revision)) throw new Error('Read ARI before starting a new pooled Unit write');",
              "  pm.environment.set('poolIfMatch', revision);",
              "  pm.environment.set('poolIdempotencyKey', pm.variables.replaceIn('{{$guid}}'));",
              "}",
              "if (!pm.environment.get('poolIfMatch')) throw new Error('Saved poolIfMatch is missing; reconcile before retrying');"
            ] } },
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('Pool ARI applied', function () { pm.response.to.have.status(200); });",
              "if (pm.response.code === 200) pm.environment.set('calendarRevision', pm.response.json().data.calendar_revision);"
            ] } }
          ]
        },
        {
          "name": "Readback before a new ARI write",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/properties/{{propertyId}}/ari?date_from={{dateFrom}}&date_to={{dateTo}}",
            "description": "## Readback before a new ARI write\n\nRefresh the current calendar revision. This request never clears a saved idempotency key or precondition; after a confirmed or manually reconciled outcome, clear only the matching key yourself before a new logical write.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `propertyId` to the intended value; use returned UUIDs for resource identifiers.\n- Set `dateFrom` to a future property-local `YYYY-MM-DD` date; ARI ranges include both endpoints.\n- Set `dateTo` to the final inclusive property-local `YYYY-MM-DD` date, on or after `dateFrom`.\n- For writes, wait for operator approval and read the current calendar revision first.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [
            { "listen": "test", "script": { "type": "text/javascript", "exec": [
              "pm.test('ARI readback', function () { pm.response.to.have.status(200); });",
              "if (pm.response.code === 200) pm.environment.set('calendarRevision', pm.response.json().data.calendar_revision);"
            ] } }
          ]
        }
      ]
    },
    {
      "name": "04 Diagnostics",
      "description": "## Diagnostics\n\nRead redacted request outcomes, field audits and asynchronous operation status. Use returned UUIDs and request IDs; do not guess internal database IDs. An accepted write or queued operation is not proof that background work completed.",
      "item": [
        {
          "name": "List recent request audit",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Request audit list response', function () { pm.response.to.have.status(200); });",
            "if (pm.response.code === 200) {",
            "  const data = pm.response.json().data;",
            "  pm.test('Request audit is an array', function () { pm.expect(data).to.be.an('array'); });",
            "  if (data.length) pm.environment.set('requestId', data[0].request_id);",
            "}"
          ] } }],
          "request": { "description": "## List recent request audit\n\nInspect recent authenticated request outcomes for this connection and automatically save the latest returned `request_id` for detail. If the ledger is empty, wait before running Read request audit.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n\n### Expected result\n\nExpect **`200`**. Inspect the response data against the OpenAPI contract. Pending/running work is not terminal success; a failed operation is a failed test.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "GET", "url": "{{baseUrl}}/requests?page=1" }
        },
        {
          "name": "Read request audit",
          "request": {
            "method": "GET",
            "url": "{{baseUrl}}/requests/{{requestId}}",
            "description": "## Read request audit\n\nInspect the redacted outcome of an authorized request.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Use a server-issued `X-Request-Id` or a `request_id` returned by the ledger; do not invent one.\n\n### Expected result\n\nExpect **`200`**. Check the response data and saved environment variables before continuing.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery."
          },
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Request audit response', function () { pm.response.to.have.status(200); });"
          ] } }]
        },
        {
          "name": "Check async operation",
          "event": [{ "listen": "test", "script": { "type": "text/javascript", "exec": [
            "pm.test('Operation status response', function () { pm.response.to.have.status(200); });",
            "if (pm.response.code === 200) {",
            "  const data = pm.response.json().data;",
            "  pm.test('Operation identity and lifecycle', function () { pm.expect(data.id).to.equal(pm.environment.get('operationId')); pm.expect(['pending', 'running', 'succeeded', 'failed']).to.include(data.status); });",
            "  pm.test('Operation has no terminal failure', function () { pm.expect(data.status).to.not.equal('failed'); });",
            "}"
          ] } }],
          "request": { "description": "## Check async operation\n\nRead the operation returned by an asynchronous write. Verify terminal success or inspect the documented failure code before proceeding.\n\n### Before you send\n\n- Select the authorized environment; confirm `baseUrl` and the local `apiKey`.\n- Set `operationId` to the intended value; use returned UUIDs for resource identifiers.\n\n### Expected result\n\nExpect **`200`**. Inspect the response data against the OpenAPI contract. Pending/running work is not terminal success; a failed operation is a failed test.\n\n### Retries and errors\n\nRead-only: retry a transient failure with backoff. Honor `Retry-After`; inspect the documented problem response for other errors.\n\nInspect `code`, `status`, field pointer, `retryable`, recovery context and request ID in `application/problem+json` errors. See the [endpoint error matrix](https://outreserve.com/developers/supply/endpoint-error-matrix.md) and [error reference](https://outreserve.com/developers/supply/errors.md) for operation-specific recovery.", "method": "GET", "url": "{{baseUrl}}/operations/{{operationId}}" }
        }
      ]
    }
  ]
}
