- You are building a service that both submits SOVs and reacts to their results, and you want one polling loop to drive new work and track its outcomes.
- You need to follow each submission’s full lineage, from the original parse through every later revision, grouped under one submission.
- You apply corrections back to a SOV as part of the same integration that submitted it, and want the resulting update tracked alongside everything else.
- You want a single long-running process to coordinate submission, update, and download, rather than separate scripts for each stage.
{id}) to go through the workflow using cURL.
This workflow demonstrates how to:
- Submit SOV parsing jobs via Start SOV Parsing Job.
- Submit an update (SUD) against a completed job via Initiate SOV Update Job, Add Locations to SOV Update Job, and Start SOV Update Job.
- Poll List Historical SOVs to track every new revision.
- Group revisions by submission to follow each submission’s full lineage.
- Detect data-ready revisions and download their outputs via Get Or Create SOV Output.
1. Submit a Parsing Job
USER ACTION Upload an Excel workbook to start an SOV parsing job. Save the returnedid. Later history polls will surface this submission’s revisions as Ping processes it. See Process an SOV for a focused walk-through of this endpoint.
Example code:
build_sov_pipeline.py
JSON output
2. Ping Processes the Submission
PING Ping parses the workbook and creates an original SOV record withrecord_type set to ORIG. Ping HITL operators then advance the submission through additional revisions, each appearing in the history feed with its own record_type:
ORIG— original SOV from the initial parse.SCRUB,AIR,RMS,RMS_ANALYSIS,API— output-format-specific revisions, each producing a downloadable artifact.COMPLETE— scrubbing complete.READY_FOR_REVIEW— awaiting HITL review.PINGREADY— Ping has marked the data ready for the consumer.PRECERTIFIED— clone pre-certified.MODELING_FILES_CREATED— modeling files generated.
is_data_ready field. PINGREADY and PRECERTIFIED revisions are always data-ready, and other revisions can become ready too. Step 5 watches is_data_ready rather than matching specific record_type values, so it catches every ready revision.
3. Poll History and Track Submissions
USER ACTION Poll List Historical SOVs for new revisions. Group them by submission so you can follow each submission’s full lineage. Records carry both apingid (linking to a Ping.Vision submission when present) and a sovid. Fall back to sovid when pingid is null so every record gets grouped. See Monitor SOV Activity for a focused walk-through of the polling and cursor mechanics.
status uses single-letter codes: C for complete and F for failed.
Example code:
build_sov_pipeline.py
JSON output
4. Submit an Update from the Poll Loop
USER ACTION An SOV must finish parsing before it can be updated. When the firstORIG record for one of the SOVs this script submitted arrives complete (status C), drive one update against its sovid. The demo tracks its own job IDs in submitted_job_ids so it updates a SOV it created rather than any unrelated record that happens to appear in the feed. The update runs three calls in order: Initiate SOV Update Job opens the job, Add Locations to SOV Update Job uploads the revised building attributes, and Start SOV Update Job begins processing. A SUD reuses its parent’s sovid and pingid, so its revisions group under the same submission and surface in the same history feed. They arrive with an id like s-lo-ping-9xkw3m-r001, an incremented revision, and a record_type of API, the default when the update job does not set an update_type. See Update an SOV for a focused walk-through of these three endpoints, the update_type values, status polling, and direct output download.
The rows in your locations CSV must reference buildings present in the parent SOV, by item_key or by sheet_name plus sheet_row_number. Submit the update once. The flag in the demo guards against re-firing on later polls.
Example code:
build_sov_pipeline.py
JSON output
sovid and pingid, so the loop in step 3 groups it under the same submission
without printing a new one.
Example history record (SUD):
JSON output
5. Fetch Outputs When Data Is Ready
USER ACTION When a revision arrives withis_data_ready set to true, request its output via POST /sov/{id}/get_or_create_output. Pass revision: -1 in the body to request the latest revision’s output regardless of which specific record id you provide. The response carries the output’s status, download URL, and filename. When request.status is COMPLETE, fetch the file from result.url and write it to disk.
Output generation is asynchronous, so a data-ready revision does not mean its output file exists yet. The demo queues these records in pending_downloads and retries each one on later polls until request.status reaches COMPLETE or FAILED, rather than blocking the poll loop on a single file.
A failed SUD never appears in the history feed, so polling alone would not tell you an update failed. The demo tracks the update it submitted through Check SOV Update Status until that job reaches COMPLETE or FAILED. On COMPLETE, it queues the update’s own output for download. Passing the SUD id to Get or Create Output returns that revision’s output directly, so the revision field does not apply.
Example code:
build_sov_pipeline.py
JSON output
Python Demo
A runnable script that submits an initial batch of parsing jobs, submits one update against the first job that completes, polls the history endpoint, groups revisions by submission, and downloads outputs when Ping HITL marks a revision data-ready. SetSOVFIXER_AUTH_TOKEN, place parse_sov_testfile.xlsx and corrections.csv in the working directory, then run with python build_sov_pipeline.py.
Download Python Script
|||
Download Example SOV
|||
Download corrections.csv
build_sov_pipeline.py