Skadi Partner API Console

Partner playbook

Submit better. Earn faster.

Every submission you POST to /create-submission is graded into one of three tiers based on the structured data you send.

Higher-tier submissions earn clearance status, block the market against duplicate filings, and surface as a "complete package" in your dashboard insights. Lower-tier submissions still get a number — they just don't reserve the account.

This is the same model the GUI applies to underwriter-typed submissions. The grade is structural: it's derived from data, not a checkbox you tick. We do this so a broker who comes in with a complete file isn't out-flanked by someone who just typed a named insured + FEIN to claim market.

The three tiers

TierYou earnYou provide
Tier 1 — Indication
Exploring appetite
A submission number. Wizard-quality state. No clearance, no market block.
  • Named insured, FEIN, NAICS, address state
  • Effective + expiration dates
  • At least one tower (line + limit)
  • Broker email
Tier 2 — Quote-ready
Block the market
Cleared status + market block during the in-window period (default 90 days). Carrier UW assigned.
  • Everything in Tier 1
  • prior_policies[] — schedule of underlying for every tower line
  • Loss summary — claims[] OR loss_attestation: {years_clean ≥5, prior_carriers}
  • operations_description (≥50 chars)
Tier 3 — Bind-ready
Visible recognition
Tier 2 + "complete package" badge in your dashboard. Faster UW review, partner-tier signal.
  • Everything in Tier 2
  • signed_application: { url, sha256, signer_name, signer_title, signed_at }
  • loss_run_files[] — currently-valued PDFs from prior carriers
  • underlying_quote_files[] — primary quote PDFs
  • naics_supplemental (high-hazard classes only — hazard grade ≥ 3)

What changes between tiers

Same endpoint, same auth, same response shape. The diff is in the request body. Here's a Tier 1 → 2 → 3 progression for the same account:

Tier 1 — Indication

Just enough to reserve a submission number. Use this when you're triaging appetite or pre-flighting a clearance check. Will not block the market.

POST /create-submission

{
  "named_insured":   "Acme Restaurants LLC",
  "fein":            "12-3456789",
  "naics_code":      "722511",
  "state":           "TX",
  "effective_date":  "2026-05-01",
  "expiration_date": "2027-05-01",
  "broker_email":    "jane@acmebrokers.com",
  "agency_id":       "<your agency uuid>",
  "towers": [
    { "line_type": "GL", "limit": 5000000, "attachment": 0 }
  ]
}

200 { "submission_grade": "tier_1", "missing_for_tier_2": [...], ... }

Tier 2 — Quote-ready (earns market block)

Add the structured-data equivalents of an ACORD package. The data IS the document — we don't need a PDF for the carrier to rate.

POST /create-submission

{
  ... // all Tier 1 fields above

  "operations_description": "Acme operates 12 fast-casual restaurants across Texas with on-site food preparation. No alcohol service. Avg 35 employees per location.",

  "prior_policies": [
    {
      "carrier":           "Liberty Mutual",
      "line_type":         "GL",
      "limit_amount":      1000000,
      "attachment":        0,
      "effective_date":    "2025-05-01",
      "expiration_date":   "2026-05-01",
      "premium":           18500
    }
  ],

  "loss_attestation": {
    "years_clean":     5,
    "prior_carriers":  ["Liberty Mutual"]
  }
  // OR provide claims[] with valuation_date + carrier_source per claim
}

200 { "submission_grade": "tier_2", "missing_for_tier_2": [], "clearance": { "decision": "proceed", ... } }

Tier 3 — Bind-ready (visible "complete package")

Add file pointers for the carrier-issued documents. We don't host these — you provide URL + SHA-256 hash + signer metadata. The hash + signed timestamp give us an audit anchor without requiring you to upload the file.

For high-hazard NAICS classes (hazard grade ≥ 3 in our hazard table — construction, hospitality/liquor, trucking, habitational, etc.), Tier 3 also requires naics_supplemental with class-specific exposure detail. This matches how the E&S excess casualty market actually operates: class supplements are a bind-time, insured-signed artifact, not a quote-time gate (Kinsale, Burns & Wilcox, ACORD-published forms all follow this pattern). At Tier 2 we don't require it; the supplement only blocks promotion to Tier 3.

The shape is permissive — any non-empty object satisfies the grader. The GUI form uses the schemas below per NAICS family; partner submissions are welcome to mirror these or send their own equivalent fields:

  • Construction (NAICS 23xxxx): subcontractor_pct, pct_residential, max_height_of_work_ft, demolition_exposure, roofing_pct
  • Hospitality / liquor (NAICS 722xxx): pct_alcohol_sales, hours_past_11pm, security_on_premises, dance_floor
  • Trucking / motor carrier (NAICS 484xxx): fleet_size, radius_miles, dot_safety_score, hazmat_bool
  • Habitational (NAICS 531110, 721110, 623xxx, …): unit_count, pool_bool, waterfront_bool, security_24h_bool
  • Manufacturing (NAICS 31–33xxxx): hot_work_bool, products_distributed_states, recalls_last_5yr
  • Generic fallback (any other high-hazard class): risk_narrative (≥ 100 chars)
POST /create-submission

{
  ... // all Tier 2 fields above

  "signed_application": {
    "url":           "https://docs.acmebrokers.com/acme-acord125-2026.pdf",
    "sha256":        "a7c4e5f3b8...",
    "signer_name":   "Jane Doe",
    "signer_title":  "Chief Operating Officer",
    "signed_at":     "2026-04-25T15:23:00Z"
  },
  "loss_run_files": [
    { "url": "https://docs.acmebrokers.com/loss-2025.pdf", "carrier": "Liberty Mutual", "valuation_date": "2026-04-15" }
  ],
  "underlying_quote_files": [
    { "url": "https://docs.acmebrokers.com/liberty-quote.pdf", "carrier": "Liberty Mutual" }
  ],

  // High-hazard classes only. Permissive shape — any non-empty object
  // satisfies the grader. Per-class field schemas are forthcoming; for
  // now, send what your underwriter would expect on the carrier's
  // class-specific supplement (e.g. McGowan Habitational, CRC Trucking).
  "naics_supplemental": {
    "subcontractor_pct":     30,
    "pct_residential":       20,
    "max_height_of_work_ft": 25
  }
}

200 { "submission_grade": "tier_3", ... }

Why this exists

Two reasons. First, parity: an underwriter typing a submission into our GUI is graded the same way. We don't want partners to be second-class citizens — you can earn (and block) clearance the same way an internal UW can. The /clearance decision controls (override, merge) are also exposed via this endpoint when there's a real conflict.

Second, shell-submission defense. The honor-system "I have all the docs" checkbox is trivially gameable — you tick a box, you claim market. Replacing the checkbox with structured fields means "I have docs" becomes "I have data," and the data is what an underwriter would actually act on. Lying about a structured loss-attestation array is a misrepresentation under your broker contract; lying about a checkbox is just a click. The friction is calibrated: Tier 2 requires only the things you should already have at first submission. Tier 3 is the things that typically firm up between indication and bind — file pointers — and isn't required to clear or block.

Clearance gating

When you POST a Tier 2+ submission, the server re-runs clearance search internally. If there's an in-window exact-FEIN match from another partner whose submission is also Tier 2+ (so the account is "held"), you'll get a 409 Conflict with the matching submission's identifier:

HTTP/1.1 409 Conflict
content-type: application/problem+json

{
  "type":   "about:blank",
  "title":  "Clearance conflict",
  "status": 409,
  "detail": "An in-window submission with this FEIN already exists ...",
  "blocking_matches": [
    { "matched_submission_id": "...", "matched_named_insured": "...", "matched_at": "..." }
  ]
}

To proceed anyway, retry with a clearance decision in the body:

{
  ...your original submission body,

  "clearance": {
    "decision":         "override",
    "override_reason":  "Insured switched broker on 2026-04-20; we have BOR letter on file."
  }
}

Or merge into the existing submission:

{
  ...,
  "clearance": {
    "decision":                 "merge",
    "merge_into_submission_id": "<the matched_submission_id from the 409 response>"
  }
}

Insights — your grade over time

Your developer dashboard (sign-in required) shows the last-30-day distribution of your submissions across tiers, and the single Tier 2 field most often missing from your Tier 1 traffic. Use it to find the leak in your integration: usually one missing section of the payload accounts for the bulk of your Tier 1 downgrades.

What we don't do

  • We don't fetch or scan the URLs you provide for signed_application, loss_run_files, or underlying_quote_files. We record metadata (URL, hash, signer) for audit. If a hash mismatch surfaces during UW review, you have a problem to explain — not us.
  • We don't require Tier 3 to clear. It's a recognition signal, not a gate. A clean Tier 2 submission gets the same clearance and market block as a Tier 3 one — it just doesn't earn the badge.
  • We don't use OCR / LLM extraction on uploaded files (yet). Structured data is the contract.