Submit a filing

A filing is the record you submit to Valley Insurance after a policy is bound, so we can report it to the state and collect the required taxes and fees. This recipe walks through the whole process: find the state, upload your document, create the filing, then track it.

Already have a price?

If you only need the taxes and fees for a policy, and aren't ready to actually file, use Price a policy instead. This recipe is for when you're ready to submit.

Run it as a script

Want to see this whole recipe run end to end before writing your own integration? The Overview has downloadable, self-contained scripts, one for Node and one for bash, that do exactly what steps 1 through 4 below describe, against the real API. See Run the whole flow for the download links, requirements, and a warning that it creates a real test filing.

Step 1: find the state and its requirements

Call GET /partner/filing-states to list the states your account can file in, along with each state's requirements and the id you'll need later as filingStateId.

curl "$BASE_URL/partner/filing-states" -H "PartnerKey: $PARTNER_KEY"

Response (one entry, trimmed):

[
  {
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "Washington",
    "stateAbbr": "WA",
    "descriptionNb": "<ol><li>Signed application</li><li>Declarations page, within 60 days of binding</li></ol>",
    "descriptionEd": "<ol><li>Endorsement declarations page</li></ol>",
    "filesNb": [
      { "id": "...", "name": "Declarations page", "createdAt": "...", "updatedAt": "...", "fileName": null, "filePath": null }
    ],
    "filesEd": [
      { "id": "...", "name": "Endorsement declarations page", "createdAt": "...", "updatedAt": "...", "fileName": null, "filePath": null }
    ],
    "nbStateRates": { "...": "raw fee-engine config, see below" },
    "edStateRates": { "...": "raw fee-engine config, see below" }
  }
]
FieldMeaning
idSave this. It's the filingStateId you pass to /create-filing.
descriptionNb / descriptionEdRequirements for new-business vs. endorsement filings in this state, as an HTML string (render it, don't print it raw).
filesNb / filesEdThe documents this state expects for each filing type (name only, these aren't files you download, they describe what to upload).
nbStateRates / edStateRatesRaw rate configuration. You don't need these to submit a filing, see State pricing and requirements if you're curious.

Before you upload anything, read the descriptionNb/descriptionEd that matches your filingType and gather every document listed in the matching filesNb/filesEd array. Full breakdown of both fields, plus a worked California example, in State pricing and requirements.

Filter to one state with ?state=WA, or check enabledStates on GET /partner/me to see which states your account can file in at all. If a state you need isn't in your enabledStates, contact us at gina@valleyinsllc.com to request access before you build against it.

Match filingType to NB or ED

Use descriptionNb / filesNb when your filingType is NEW_BUSINESS or NEW_BUSINESS_RENEWAL. Use descriptionEd / filesEd for ENDORSEMENT_ADDITIONAL or ENDORSEMENT_RETURN.

Step 2: upload your document

Ask for a signed upload URL, then PUT your file to it.

curl -X POST "$BASE_URL/partner/upload-user-file" \
  -H "PartnerKey: $PARTNER_KEY" -H "Content-Type: application/json" \
  -d '{
        "fileName": "policy-declarations.pdf"
      }'

Response:

{
  "uploadUrl": "https://storage.googleapis.com/...",
  "fileName": "policy-declarations.pdf",
  "storagePath": "partner-uploads/3fa8.../policy-declarations.pdf"
}

Now upload the actual file bytes to uploadUrl:

curl -X PUT "$UPLOAD_URL" \
  -H "Content-Type: application/pdf" \
  --data-binary @policy-declarations.pdf

Keep storagePath from the response. You'll use it as filePath in the next step.

filingId is optional here

UploadUserFileDTO also accepts an optional filingId, for attaching a file to a filing that already exists. For a brand-new filing, leave it out and pass storagePath in /create-filing instead (step 3).

Step 3: create the filing

curl -X POST "$BASE_URL/partner/create-filing" \
  -H "PartnerKey: $PARTNER_KEY" -H "Content-Type: application/json" \
  -d '{
        "filingType": "NEW_BUSINESS",
        "filingStateId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "policyNumber": "POL-2026-00123",
        "insuredsName": "Acme Warehousing LLC",
        "carriersName": "Acme Surplus Lines Carrier",
        "policyEffectiveDate": "2026-08-01",
        "premium": 12500,
        "files": [
          {
            "name": "Declarations page",
            "fileName": "policy-declarations.pdf",
            "filePath": "partner-uploads/3fa8.../policy-declarations.pdf"
          }
        ]
      }'

Required fields:

FieldMeaning
filingTypeSame enum as /calculate. See Price a policy for the four values.
filingStateIdThe id from step 1.
policyNumberThe insured's policy number.
insuredsNameName of the insured.
carriersNameName of the surplus-lines carrier.
policyEffectiveDateWhen the policy takes effect.
premiumThe policy premium.
filesArray of { name, fileName, filePath }. filePath is the storagePath from step 2.

Common optional fields: endorsementNumber and endorsementEffectiveDate (for endorsement filings), policyFee, inspectionFee, carriersFee, lgtValue, fmtValue, declaredPaymentMethod (ACH, WIRE, CHECK, PENDING_INVOICE, or INVOICED), and userNotes.

The response is the created filing:

{
  "id": "b1f2c3d4-...",
  "filingType": "NEW_BUSINESS",
  "userId": "u_123",
  "filingStateId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "filingState": { "id": "3fa85f64-...", "name": "Washington", "stateAbbr": "WA" },
  "policyNumber": "POL-2026-00123",
  "insuredsName": "Acme Warehousing LLC",
  "carriersName": "Acme Surplus Lines Carrier",
  "policyEffectiveDate": "2026-08-01T00:00:00.000Z",
  "premium": 12500,
  "status": "UNPAID",
  "userFiles": [
    { "id": "...", "name": "Declarations page", "fileName": "policy-declarations.pdf", "filePath": "partner-uploads/3fa8.../policy-declarations.pdf", "createdAt": "...", "updatedAt": "..." }
  ],
  "createdAt": "2026-07-16T10:00:00.000Z"
}
No rate snapshot in the response

filingState is a lightweight summary (id, name, stateAbbr), not the full rate configuration. If you need the price, get it from /calculate before or after filing, don't try to derive it from this response.

Save id, that's what you'll poll in step 4.

Step 4: track the filing

curl "$BASE_URL/partner/{id}" -H "PartnerKey: $PARTNER_KEY"

Returns the same filing shape as step 3, with the current status:

StatusMeaning
UNPAIDFiling created, payment not yet collected.
PAIDPayment has been settled.
PENDINGFiling is being processed. Uploading a new file to a COMPLETED filing also moves it back to PENDING.
COMPLETEDValley Insurance has marked the filing done. completedAt is set.
REJECTEDThe filing was rejected. Check rejectionReason for why, and resubmit with a corrected filing.
Status isn't a strict sequence

Don't assume filings move through these five statuses in a fixed order. Treat status as "the current state," and poll it rather than predicting what comes next.

List your filings (recover a lost id)

Lost the filing id?

If you didn't save the id from step 3, or you need to look up a filing from a while back, call GET /partner/filings instead of guessing. It returns your own filings only, paginated.

curl "$BASE_URL/partner/filings?offset=0&limit=20" -H "PartnerKey: $PARTNER_KEY"

Response:

{
  "items": [
    {
      "id": "b1f2c3d4-...",
      "policyNumber": "POL-2026-00123",
      "insuredsName": "Acme Warehousing LLC",
      "carriersName": "Acme Surplus Lines Carrier",
      "status": "PAID",
      "filingState": { "id": "3fa85f64-...", "name": "Washington", "stateAbbr": "WA" }
    }
  ],
  "total": 47,
  "offset": 0,
  "limit": 20
}

Each entry in items is the same filing object returned by /create-filing and GET /partner/{id} (with the lightweight filingState summary, no rate snapshots).

ParamMeaning
offsetFilings to skip before this page starts. Defaults to 0.
limitMax filings to return, from 1 to 100. Defaults to 20.
statusOptional. Only return filings in this status.
qOptional. Free-text search across policy number, insured name, and similar fields.

To page through results, keep incrementing offset by limit and requesting again. Once offset + limit >= total, you've reached the last page.