{
  "info": {
    "name": "Skadi Partner API \u2014 OAuth 2.0",
    "description": "Reference collection for the Skadi Specialty Insurance Co. Excess Casualty Partner API \u2014 OAuth 2.0 Client Credentials mode (v1).\n\n**Source of truth:** [`/public/openapi.yaml`](https://github.com/ryan-carroll/Excess-Rater/blob/main/public/openapi.yaml) in the repo. This Postman collection is hand-curated to mirror the spec for human-driven exploration. The CI gate `scripts/test-collections-alignment.ts` fails if any spec operation is missing here (or vice versa). If a new endpoint exists in the spec but not in this collection, that's a documented bug \u2014 fix the collection, don't edit the spec.\n\n## Setup\n1. Import this collection and `Skadi-Sandbox.postman_environment.json`.\n2. Select the **Skadi Sandbox** environment.\n3. Fill in `apiKey` (plaintext, used as `client_secret`), `apiKeyId` (UUID, used as `client_id`), and `baseUrl`. Leave `hmacSecret` blank \u2014 it's unused in this mode.\n4. Run any request. The collection-level pre-request script automatically fetches and caches a bearer token on first use, refreshes 60 seconds before expiry, and attaches it as `Authorization: Bearer`.\n\n## How token management works\nThe pre-request script (collection level) checks `accessToken` + `accessTokenExpiresAt` in the environment. If missing or near-expiry, it calls `POST /oauth-token` via `pm.sendRequest`, caches the result, and proceeds. Tokens are short-lived (1 hour) HS256 JWTs. You don't need to touch the OAuth Token request manually \u2014 it's included in the collection only for debugging.\n\n## When to use OAuth vs HMAC\nOAuth keeps your raw secret out of the wire for routine calls \u2014 each request ships a short-lived token instead. HMAC is simpler (no token lifecycle) and the recommended default; pick OAuth when your platform already speaks OAuth 2.0 Client Credentials and you want symmetric treatment.\n\nKeys issued with `require_hmac=true` will reject bearer tokens (401 `invalid-credentials`). Ask your account admin to issue an OAuth-compatible key, or switch to `Skadi-Partner-API-HMAC.postman_collection.json`.\n\nFull contract: `docs/PARTNER_API.md` in the repo.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{accessToken}}",
        "type": "string"
      }
    ]
  },
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Collection-level OAuth 2.0 token manager for Skadi Partner API.",
          "// - Generates a per-request Idempotency-Key UUID (consumed by write endpoints).",
          "// - Skips token refresh for the token-endpoint request itself.",
          "// - Checks cached accessToken + accessTokenExpiresAt; refreshes only when",
          "//   missing or within 60s of expiry, otherwise reuses the cached token.",
          "",
          "pm.variables.set('idempotencyKey', (typeof crypto !== 'undefined' && crypto.randomUUID)",
          "  ? crypto.randomUUID()",
          "  : 'postman-' + Date.now() + '-' + Math.random().toString(36).slice(2, 10));",
          "",
          "if (pm.info && pm.info.requestName === 'OAuth 2.0 Token (manual refresh)') { return; }",
          "",
          "const TOKEN_VAR = 'accessToken';",
          "const EXP_VAR   = 'accessTokenExpiresAt';",
          "const now    = Date.now();",
          "const cached = pm.environment.get(TOKEN_VAR);",
          "const expAt  = parseInt(pm.environment.get(EXP_VAR) || '0', 10);",
          "",
          "if (cached && expAt > now + 60000) { return; }",
          "",
          "const baseUrl  = pm.environment.get('baseUrl') || pm.collectionVariables.get('baseUrl');",
          "const apiKeyId = pm.environment.get('apiKeyId');",
          "const apiKey   = pm.environment.get('apiKey');",
          "",
          "if (!baseUrl || !apiKeyId || !apiKey) {",
          "  console.warn('[skadi] OAuth env not fully set. Need baseUrl, apiKeyId (UUID), apiKey.');",
          "  return;",
          "}",
          "",
          "pm.sendRequest({",
          "  url: baseUrl + '/oauth-token',",
          "  method: 'POST',",
          "  header: { 'Content-Type': 'application/x-www-form-urlencoded' },",
          "  body: {",
          "    mode: 'urlencoded',",
          "    urlencoded: [",
          "      { key: 'grant_type',    value: 'client_credentials' },",
          "      { key: 'client_id',     value: apiKeyId },",
          "      { key: 'client_secret', value: apiKey }",
          "    ]",
          "  }",
          "}, (err, res) => {",
          "  if (err || !res || res.code !== 200) {",
          "    console.error('[skadi] OAuth token fetch failed:', err || (res && res.status), res && res.text && res.text());",
          "    return;",
          "  }",
          "  const j = res.json();",
          "  if (j.access_token) {",
          "    pm.environment.set(TOKEN_VAR, j.access_token);",
          "    pm.environment.set(EXP_VAR, String(Date.now() + ((j.expires_in || 3600) * 1000)));",
          "    console.log('[skadi] OAuth token cached, expires in', j.expires_in || 3600, 's');",
          "  }",
          "});"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "Rate Quote",
      "request": {
        "method": "POST",
        "description": "Compute technical + policy premium for a tower structure. Does not persist. Scope: `rate`.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"account\":{\"namedInsured\":\"Acme Contractors LLC\",\"naicsClass\":\"236220\",\"state\":\"TX\",\"exposureBase\":{\"metric\":\"payroll\",\"value\":5200000}},\"towers\":[{\"lineType\":\"GL\",\"limit\":5000000,\"attachment\":0,\"primaryLimit\":1000000,\"premPremium\":25000,\"prodPremium\":17000},{\"lineType\":\"AUTO\",\"limit\":5000000,\"attachment\":1000000,\"primaryLimit\":1000000,\"premPremium\":18000}],\"coverages\":{\"gl\":[\"premises_ops\"],\"auto\":[\"owned\"]},\"modifiers\":{\"schedule\":{\"safety_program\":-0.05},\"experience\":0.95},\"marketFactor\":1.0}"
        },
        "url": {
          "raw": "{{baseUrl}}/rate-quote",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "rate-quote"
          ]
        }
      }
    },
    {
      "name": "Appetite Check",
      "request": {
        "method": "GET",
        "description": "Composite NAICS \u00d7 state \u00d7 line appetite score. Scope: `appetite`.",
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "url": {
          "raw": "{{baseUrl}}/appetite-check?naics=236220&state=TX&line=gl",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "appetite-check"
          ],
          "query": [
            {
              "key": "naics",
              "value": "236220"
            },
            {
              "key": "state",
              "value": "TX"
            },
            {
              "key": "line",
              "value": "gl"
            }
          ]
        }
      }
    },
    {
      "name": "Hazard Lookup",
      "request": {
        "method": "GET",
        "description": "NAICS \u2192 hazard grades (premises-ops, products-completed-ops, auto, liquor). Scope: `hazard`.",
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "url": {
          "raw": "{{baseUrl}}/hazard-lookup?naics=236220",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "hazard-lookup"
          ],
          "query": [
            {
              "key": "naics",
              "value": "236220"
            }
          ]
        }
      }
    },
    {
      "name": "Clearance Pre-flight",
      "request": {
        "method": "POST",
        "description": "Pre-flight a submission. Returns redacted severity + suggested action and per-hit disposition (M-tier × G-tier × same-agency × renewal-window) for matches in your own book. Cross-tenant matches expose only the worst-case `carrier_internal_match_summary` (no PII). Scope: `clearance`.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\"named_insured\":\"Acme Industries Inc.\",\"fein\":\"12-3456789\",\"state\":\"TX\",\"naics\":\"722511\",\"zip\":\"75201\",\"documentation\":{\"acord_application\":true,\"loss_runs_5y\":true,\"supplemental_questionnaire\":false}}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{baseUrl}}/clearance-request",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "clearance-request"
          ]
        }
      }
    },
    {
      "name": "Clearance Requests List",
      "request": {
        "method": "GET",
        "description": "List your own clearance request history. Cross-tenant data is never returned. Scope: `clearance`.",
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "url": {
          "raw": "{{baseUrl}}/clearance-requests?limit=20",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "clearance-requests"
          ],
          "query": [
            {
              "key": "limit",
              "value": "20"
            }
          ]
        }
      }
    },
    {
      "name": "Clearance Match Resolve",
      "request": {
        "method": "POST",
        "description": "Persist a per-hit resolution against a clearance_match returned by /clearance-request. Multi-hit clearance results carry per-hit resolutions — match #1 can be `merged` while match #2 is `linked_related`. Idempotent on Idempotency-Key. Admin-only kinds (not_related, cleared_release, cleared_renewal_authorization) require a non-empty `note` and are RLS-gated. Scope: `clearance`.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "raw": "{\"match_id\":\"00000000-0000-0000-0000-000000000000\",\"resolution\":\"merged\",\"note\":null}",
          "options": {
            "raw": {
              "language": "json"
            }
          }
        },
        "url": {
          "raw": "{{baseUrl}}/clearance-match-resolve",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "clearance-match-resolve"
          ]
        }
      }
    },
    {
      "name": "Create Submission",
      "request": {
        "method": "POST",
        "description": "Persist a submission + quote skeleton. Supports Idempotency-Key (auto-generated per send). Scope: `write:submissions`.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"named_insured\":\"Acme Contractors LLC\",\"agency_id\":\"{{agencyId}}\",\"naics_code\":\"236220\",\"effective_date\":\"2026-06-01\",\"expiration_date\":\"2027-06-01\",\"state\":\"TX\",\"broker_email\":\"broker@example.com\",\"broker_name\":\"Jane Broker\",\"towers\":[{\"line_type\":\"GL\",\"limit\":5000000,\"attachment\":0}]}"
        },
        "url": {
          "raw": "{{baseUrl}}/create-submission",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "create-submission"
          ]
        }
      }
    },
    {
      "name": "List Policies",
      "request": {
        "method": "GET",
        "description": "Cursor-paginated list of policies. Filters: status, effective/expiration date windows, state, NAICS, named_insured (partial). Sort options: effective_date_desc (default), effective_date_asc, expiration_date_asc, expiration_date_desc, written_premium_desc. Partner keys see only their agency_group's book; admin:all keys cross tenants.\n\nScope: `read:policies`.",
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "url": {
          "raw": "{{baseUrl}}/get-policies?status=in_force&sort=effective_date_desc&limit=25",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-policies"
          ],
          "query": [
            {
              "key": "status",
              "value": "in_force"
            },
            {
              "key": "sort",
              "value": "effective_date_desc"
            },
            {
              "key": "limit",
              "value": "25"
            },
            {
              "key": "state",
              "value": "TX",
              "disabled": true
            },
            {
              "key": "naics_code",
              "value": "236220",
              "disabled": true
            },
            {
              "key": "named_insured",
              "value": "Acme",
              "disabled": true
            },
            {
              "key": "effective_date_gte",
              "value": "2026-01-01",
              "disabled": true
            },
            {
              "key": "expiration_date_lte",
              "value": "2027-12-31",
              "disabled": true
            },
            {
              "key": "cursor",
              "value": "",
              "disabled": true
            }
          ]
        }
      }
    },
    {
      "name": "Get Policy",
      "request": {
        "method": "GET",
        "description": "Single policy's current derived state: written premium, effective/expiration, status, named insured, NAICS, and the agency + agency_group that wrote it. Returns 404 if the policy is not in your tenant (doesn't distinguish from truly-missing \u2014 intentional).\n\nReplace `policyId` with a real UUID from List Policies.\n\nScope: `read:policies`.",
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "url": {
          "raw": "{{baseUrl}}/get-policies?id={{policyId}}",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-policies"
          ],
          "query": [
            {
              "key": "id",
              "value": "{{policyId}}"
            }
          ]
        }
      }
    },
    {
      "name": "Get Policy Transactions",
      "request": {
        "method": "GET",
        "description": "Full transaction history for a policy \u2014 every endorsement, cancellation, extension, reinstatement, renewal, non_renewal, audit, rewrite, and `state_transition` (calendar-emitted lifecycle advance) \u2014 ordered by sequence. Each row carries premium_change, before_state, after_state, and kind-specific fields (pro_rata_factor, cancellation_method, endorsement_details, renewal_policy_id). Tenant-guarded identically to Get Policy.\n\nScope: `read:policies`.",
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "url": {
          "raw": "{{baseUrl}}/get-policy-transactions?policy_id={{policyId}}",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-policy-transactions"
          ],
          "query": [
            {
              "key": "policy_id",
              "value": "{{policyId}}"
            }
          ]
        }
      }
    },
    {
      "name": "Process Transaction",
      "request": {
        "method": "POST",
        "description": "Post a deterministic state-flip transaction (Phase 6: reinstatement | non_renewal only). Rating-affected kinds (endorsement, cancellation, extension, audit, renewal, rewrite) moved to dedicated quote-then-bind endpoints (POST /endorsements, /cancellations, /extensions, /renewals, /rewrites, /audits, /oos-rebases) and now return 410 with extensions.redirect_endpoint. Supports Idempotency-Key. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"policy_id\":\"{{policyId}}\",\"transaction_kind\":\"reinstatement\",\"effective_date\":\"2026-09-15\",\"description\":\"Reinstate after late payment received\"}"
        },
        "url": {
          "raw": "{{baseUrl}}/process-transaction",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "process-transaction"
          ]
        }
      }
    },
    {
      "name": "List Accounts",
      "request": {
        "method": "GET",
        "description": "Canonical insured account identity. Multi-tenant: returns accounts with at least one agency relationship in your agency_group, including historical (BOR'd-away) ones.\n\nScope: `read:accounts`.",
        "url": {
          "raw": "{{baseUrl}}/get-accounts?sort=updated_at_desc&limit=25",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-accounts"
          ],
          "query": [
            {
              "key": "sort",
              "value": "updated_at_desc"
            },
            {
              "key": "limit",
              "value": "25"
            },
            {
              "key": "id",
              "value": "{{accountId}}",
              "disabled": true,
              "description": "Single-account fetch by id"
            },
            {
              "key": "naics",
              "value": "722511",
              "disabled": true
            },
            {
              "key": "state",
              "value": "TX",
              "disabled": true
            },
            {
              "key": "named_insured",
              "value": "Acme",
              "disabled": true
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "List Submissions",
      "request": {
        "method": "GET",
        "description": "Cursor-paginated list of submissions in your tenant. Partner keys see only their agency_group's book. `account_data` jsonb is intentionally excluded (PII).\n\nScope: `read:submissions`.",
        "url": {
          "raw": "{{baseUrl}}/get-submissions?sort=created_at_desc&limit=25",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-submissions"
          ],
          "query": [
            {
              "key": "sort",
              "value": "created_at_desc"
            },
            {
              "key": "limit",
              "value": "25"
            },
            {
              "key": "status",
              "value": "quoted",
              "disabled": true
            },
            {
              "key": "state",
              "value": "TX",
              "disabled": true
            },
            {
              "key": "named_insured",
              "value": "Acme",
              "disabled": true
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "Get Submission",
      "request": {
        "method": "GET",
        "description": "Single submission with agency + group details.\n\nScope: `read:submissions`.",
        "url": {
          "raw": "{{baseUrl}}/get-submissions?id={{submissionId}}",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-submissions"
          ],
          "query": [
            {
              "key": "id",
              "value": "{{submissionId}}"
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "Get Quotes (by submission)",
      "request": {
        "method": "GET",
        "description": "All quote versions for a submission, ordered by version ASC.\n\nScope: `read:quotes`.",
        "url": {
          "raw": "{{baseUrl}}/get-quotes?submission_id={{submissionId}}",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-quotes"
          ],
          "query": [
            {
              "key": "submission_id",
              "value": "{{submissionId}}"
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "Get Claims (by policy)",
      "request": {
        "method": "GET",
        "description": "Post-bind claims on a policy. For nested detail use ?id=<claimId>.\n\nScope: `read:claims`.",
        "url": {
          "raw": "{{baseUrl}}/get-claims?policy_id={{policyId}}",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-claims"
          ],
          "query": [
            {
              "key": "policy_id",
              "value": "{{policyId}}"
            },
            {
              "key": "id",
              "value": "{{claimId}}",
              "disabled": true
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "Get Documents (metadata-only)",
      "request": {
        "method": "GET",
        "description": "Logical listing of documents a policy has \u2014 one entry per transaction (binder, endorsements, cancellations) with attached ISO forms. \u26a0 Metadata-only; does NOT serve PDF bytes.\n\nScope: `read:documents`.",
        "url": {
          "raw": "{{baseUrl}}/get-documents?policy_id={{policyId}}",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-documents"
          ],
          "query": [
            {
              "key": "policy_id",
              "value": "{{policyId}}"
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "Quote PDF / ACORD Export",
      "request": {
        "method": "POST",
        "description": "Render a quote / binder / indication as PDF or ACORD JSON. Content-negotiated by Accept: application/pdf (default) returns the rendered PDF binary with an embedded JSON sidecar (PDF 1.7 EmbeddedFile); application/json returns the ACORD envelope (ACORD 137 for quote/indication, ACORD 75 for binder). NOTE: this endpoint lives on the Vercel app host ({{appBaseUrl}}), not the Supabase functions host ({{baseUrl}}). The collection-level pre-request script attaches the cached bearer token automatically. Scope: write:documents. Full contract: .claude/docs/partner-pdf-export.md.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Accept",
            "value": "application/pdf",
            "type": "text",
            "description": "Content negotiation. application/pdf (default) returns the rendered PDF; application/json returns the ACORD envelope."
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"quoteId\":\"{{quoteId}}\",\"documentType\":\"quote\"}"
        },
        "url": {
          "raw": "{{appBaseUrl}}/api/partner/quote-pdf",
          "host": [
            "{{appBaseUrl}}"
          ],
          "path": [
            "api",
            "partner",
            "quote-pdf"
          ]
        }
      }
    },
    {
      "name": "Get Reports",
      "request": {
        "method": "GET",
        "description": "Tenant-scoped aggregated reports. Allowed types: broker_scorecard, submission_funnel, book_of_business, loss_ratio_monthly, premium_trend_monthly.\n\nScope: `read:reports`.",
        "url": {
          "raw": "{{baseUrl}}/get-reports?type=broker_scorecard",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "get-reports"
          ],
          "query": [
            {
              "key": "type",
              "value": "broker_scorecard"
            },
            {
              "key": "start_date",
              "value": "2026-01-01",
              "disabled": true
            },
            {
              "key": "end_date",
              "value": "2026-12-31",
              "disabled": true
            }
          ]
        },
        "header": [
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ]
      }
    },
    {
      "name": "OAuth 2.0 Token (manual refresh)",
      "request": {
        "method": "POST",
        "description": "Manual token exchange for debugging. You do NOT need to run this before other requests \u2014 the collection's pre-request script handles token fetch + cache + refresh automatically. Useful for confirming your credentials, inspecting `scope` claims, or forcing an immediate refresh.\n\nRFC 6749 \u00a74.4 Client Credentials grant. Token TTL is 1 hour. Keys with `require_hmac=true` will be rejected here (401) \u2014 use the HMAC collection instead.",
        "auth": {
          "type": "noauth"
        },
        "header": [
          {
            "key": "Content-Type",
            "value": "application/x-www-form-urlencoded"
          }
        ],
        "body": {
          "mode": "urlencoded",
          "urlencoded": [
            {
              "key": "grant_type",
              "value": "client_credentials"
            },
            {
              "key": "client_id",
              "value": "{{apiKeyId}}"
            },
            {
              "key": "client_secret",
              "value": "{{apiKey}}"
            },
            {
              "key": "scope",
              "value": "rate appetite hazard",
              "description": "Optional. Must be subset of key's scopes."
            }
          ]
        },
        "url": {
          "raw": "{{baseUrl}}/oauth-token",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "oauth-token"
          ]
        },
        "event": [
          {
            "listen": "test",
            "script": {
              "type": "text/javascript",
              "exec": [
                "// Cache the manually-fetched token so subsequent requests reuse it.",
                "if (pm.response.code === 200) {",
                "  const j = pm.response.json();",
                "  if (j.access_token) {",
                "    pm.environment.set('accessToken', j.access_token);",
                "    pm.environment.set('accessTokenExpiresAt', String(Date.now() + ((j.expires_in || 3600) * 1000)));",
                "    console.log('[skadi] manually refreshed; token cached for', j.expires_in || 3600, 's');",
                "  }",
                "}"
              ]
            }
          }
        ]
      }
    },
    {
      "name": "Create Endorsement (draft)",
      "request": {
        "method": "POST",
        "description": "Create a priced endorsement draft (quote-then-bind). Server applies structured ops to the snapshot, re-rates, returns pro-rated delta + valid_until + links.{self,bind,abandon}. Bind separately with POST /endorsements/{id}/bind + Idempotency-Key. PATCH the draft to mutate + re-rate. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"policy_id\":\"{{policyId}}\",\"effective_date\":\"2026-08-15\",\"description\":\"Bump GL tower to $10M\",\"changes\":[{\"op\":\"change_limit\",\"tower_id\":\"{{towerId}}\",\"new_limit\":10000000}]}"
        },
        "url": {
          "raw": "{{baseUrl}}/endorsements",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "endorsements"
          ]
        }
      }
    },
    {
      "name": "Bind Endorsement",
      "request": {
        "method": "POST",
        "description": "Commit the endorsements draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/endorsements/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "endorsements",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    },
    {
      "name": "Bulk Endorsements (create+bind)",
      "request": {
        "method": "POST",
        "description": "Create+bind up to 50 endorsements in one request. Each item is create-then-bind, processed independently — the response is a partial-success report (succeeded[]/failed[]), not all-or-nothing. A per-item idempotency_key (required) threads through draft creation and bind, so replays short-circuit at commit and never double-bind. Max 50 items. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"items\":[{\"idempotency_key\":\"bulk-item-1\",\"policy_id\":\"{{policyId}}\",\"effective_date\":\"2026-08-15\",\"description\":\"Bump GL tower to $10M\",\"changes\":[{\"op\":\"change_limit\",\"tower_id\":\"{{towerId}}\",\"new_limit\":10000000}]},{\"idempotency_key\":\"bulk-item-2\",\"policy_id\":\"{{policyId}}\",\"effective_date\":\"2026-09-01\",\"description\":\"Raise attachment\",\"changes\":[{\"op\":\"change_attachment\",\"tower_id\":\"{{towerId}}\",\"new_attachment\":2000000}]}]}"
        },
        "url": {
          "raw": "{{baseUrl}}/endorsements/bulk",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "endorsements",
            "bulk"
          ]
        }
      }
    },
    {
      "name": "Create Cancellation (draft)",
      "request": {
        "method": "POST",
        "description": "Create a cancellation draft. method=pro_rata|short_rate (legacy 'flat' removed). Server computes return_premium against MEP floor, short_rate_penalty (if applicable), commission_clawback. Bind with POST /cancellations/{id}/bind + Idempotency-Key. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"policy_id\":\"{{policyId}}\",\"cancellation_date\":\"2026-09-01\",\"method\":\"pro_rata\",\"notice_date\":\"2026-08-15\",\"reason_code\":\"INSURED_REQ\"}"
        },
        "url": {
          "raw": "{{baseUrl}}/cancellations",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "cancellations"
          ]
        }
      }
    },
    {
      "name": "Bind Cancellation",
      "request": {
        "method": "POST",
        "description": "Commit the cancellations draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/cancellations/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "cancellations",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    },
    {
      "name": "Create Extension (draft)",
      "request": {
        "method": "POST",
        "description": "Extend the policy expiration. Server pro-rates daily premium rate over the extension period and refreshes MEP for the new term length. Bind with POST /extensions/{id}/bind + Idempotency-Key. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"policy_id\":\"{{policyId}}\",\"extended_expiration\":\"2026-12-31\",\"effective_date\":\"2026-09-15\"}"
        },
        "url": {
          "raw": "{{baseUrl}}/extensions",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "extensions"
          ]
        }
      }
    },
    {
      "name": "Bind Extension",
      "request": {
        "method": "POST",
        "description": "Commit the extensions draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/extensions/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "extensions",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    },
    {
      "name": "Create Renewal (draft)",
      "request": {
        "method": "POST",
        "description": "Create a successor-policy draft for renewal. Successor is rated at the FactorVersion effective on new_effective_date \u2014 filed rate revisions automatically apply. Bind atomically emits 'renewal' txn on prior (status \u2192 renewed) + creates successor (status=bound, prior_policy_id back-ref). 7-day TTL. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"prior_policy_id\":\"{{policyId}}\",\"new_effective_date\":\"2027-01-01\",\"new_expiration_date\":\"2028-01-01\"}"
        },
        "url": {
          "raw": "{{baseUrl}}/renewals",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "renewals"
          ]
        }
      }
    },
    {
      "name": "Bind Renewal",
      "request": {
        "method": "POST",
        "description": "Commit the renewals draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/renewals/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "renewals",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    },
    {
      "name": "Create Rewrite (draft)",
      "request": {
        "method": "POST",
        "description": "Off-cycle replacement: terminate-and-reissue mid-term. Same successor-rating semantics as renewal. Named-insured changes flow through here per Guidewire/Duck Creek convention. 7-day TTL. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"prior_policy_id\":\"{{policyId}}\",\"rewrite_date\":\"2026-09-01\",\"new_expiration_date\":\"2027-09-01\",\"reason\":\"Restructure attachment\"}"
        },
        "url": {
          "raw": "{{baseUrl}}/rewrites",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "rewrites"
          ]
        }
      }
    },
    {
      "name": "Bind Rewrite",
      "request": {
        "method": "POST",
        "description": "Commit the rewrites draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/rewrites/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "rewrites",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    },
    {
      "name": "Create Audit (draft)",
      "request": {
        "method": "POST",
        "description": "Reported-exposure premium audit. Server computes (reported - rated) \u00d7 rate_per_unit per exposure and sums. basis='manual' requires write:transactions:override (internal-only); partners use the structured form. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"policy_id\":\"{{policyId}}\",\"audit_period_start\":\"2025-06-01\",\"audit_period_end\":\"2026-05-31\",\"exposures\":[{\"basis\":\"payroll\",\"rated_amount\":2000000,\"reported_amount\":2400000,\"rate_per_unit\":0.0085}]}"
        },
        "url": {
          "raw": "{{baseUrl}}/audits",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "audits"
          ]
        }
      }
    },
    {
      "name": "Bind Audit",
      "request": {
        "method": "POST",
        "description": "Commit the audits draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/audits/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "audits",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    },
    {
      "name": "Create OOS Rebase (draft)",
      "request": {
        "method": "POST",
        "description": "Insert an endorsement with effective date BEFORE later applied transactions. Server walks downstream txns and emits a void-offset-replace plan in rated_result.rows for review before bind. Scope: write:transactions.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{\"policy_id\":\"{{policyId}}\",\"oos_effective_date\":\"2026-04-15\",\"oos_premium_change\":1500,\"description\":\"Retroactive limit increase\"}"
        },
        "url": {
          "raw": "{{baseUrl}}/oos-rebases",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "oos-rebases"
          ]
        }
      }
    },
    {
      "name": "Bind OOS Rebase",
      "request": {
        "method": "POST",
        "description": "Commit the oos-rebases draft. Idempotency-Key is required. Returns 409 stale-snapshot with extensions.fresh_draft if the policy state drifted between draft creation and bind \u2014 supersede + retry pattern.",
        "header": [
          {
            "key": "Content-Type",
            "value": "application/json"
          },
          {
            "key": "Idempotency-Key",
            "value": "{{idempotencyKey}}"
          },
          {
            "key": "Skadi-API-Version",
            "value": "2026-04-25",
            "type": "text",
            "description": "Skadi API contract version. Omit to use the version pinned to your API key at issuance."
          }
        ],
        "body": {
          "mode": "raw",
          "options": {
            "raw": {
              "language": "json"
            }
          },
          "raw": "{}"
        },
        "url": {
          "raw": "{{baseUrl}}/oos-rebases/{{draftId}}/bind",
          "host": [
            "{{baseUrl}}"
          ],
          "path": [
            "oos-rebases",
            "{{draftId}}",
            "bind"
          ]
        }
      }
    }
  ],
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://tyimzxmwppgiycvcdxvl.supabase.co/functions/v1"
    },
    {
      "key": "appBaseUrl",
      "value": "https://app.skadispecialty.com"
    },
    {
      "key": "quoteId",
      "value": "00000000-0000-0000-0000-000000000000"
    },
    {
      "key": "policyId",
      "value": "00000000-0000-0000-0000-000000000000"
    },
    {
      "key": "agencyId",
      "value": "00000000-0000-0000-0000-000000000000"
    },
    {
      "key": "draftId",
      "value": "00000000-0000-0000-0000-000000000000"
    },
    {
      "key": "towerId",
      "value": "00000000-0000-0000-0000-000000000000"
    }
  ]
}
