### Python: Example Response (Generation Started) Source: https://docs.pingintel.com/workflows/ping-extraction/get-or-create-output Example response when the output generation has started. The request status is PENDING and includes a request ID for polling. ```python { "request": { "id": "9f4d8c10-3b7e-4a52-bd91-c823f15e4d76", "status": "PENDING" } } ``` -------------------------------- ### Example Email Download Link Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Link to download the example email file demo_email.eml from the pingintel-api GitHub repository. ```html Download Example Email here ``` -------------------------------- ### Python Download Output Example Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Example Python output showing the download messages for AirModeler and JSON files from the Ping.Vision API. ```python Downloading AirModeler: Acme Corp 2026-02-AirModeler.xlsm from https://vision.pingintel.com/api/v1/sov/019c7d3e-0001-7abc-9000-abcdef123456/output/Acme%20Corp%202026-02-AirModeler.xlsm Downloading JSON: Acme Corp 2026-02.json from https://vision.pingintel.com/api/v1/sov/019c7d3e-0001-7abc-9000-abcdef123456/output/Acme%20Corp%202026-02.json ``` -------------------------------- ### Example Response (JSON) Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Shows a truncated example of the JSON response from the submission events endpoint. It includes a cursor ID and an array of results, each containing event type, message, and ping ID. ```json { "cursor_id": "019c7d3e-dd84-74f1-a7a1-cc41ee75ad8e", "results": [ { "event_type": "SSC", "message": "Submission status was changed from Data Entry to Underwriting", "pingid": "p-mk-tempo-esw5ab", "...": "..." }, "...", ] } ``` -------------------------------- ### cURL command to list submission events Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage GET request to the submission-events endpoint with query parameters for pingid, start time, page size, team, and division. Replace {id}, {team_uuid}, {division_uuid}, and with actual values. ```shell curl --request GET \ --url "https://vision.pingintel.com/api/v1/submission-events?pingid={id}&start=20260220000000&page_size=50&team={team_uuid}&division={division_uuid}" \ --header "Authorization: Token " ``` -------------------------------- ### OC Event Metadata JSON Example Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Example JSON response from the Ping.Vision API showing an Outputters Complete (OC) event. Contains cursor_id, results array with event details, and metadata including job_id, submission_status, and outputs array with file URLs. ```json { "cursor_id": "019c7d3e-dd84-74f1-a7a1-cc41ee75ad8e", "results": [ { "uuid": "019d73c0-2a2e-766f-bdfb-45a9bea7c213", "created_time": "2026-04-09T19:37:46.798287Z", "event_type": "OC", "message": "Outputters complete", "pingid": "p-mk-tempo-esw5ab", "division_uuid": "12345678-abc1-cde2-efg3-123456789abcd", "new_value": null, "old_value": null, "user_id": 13, "metadata": { "job_id": "93af186e-344b-11f1-91fb-922cce342ed8", "submission_status": "Underwriting", "sudid": "019c7d3e-0001-7abc-9000-abcdef123456", "outputs": [ { "label": "Ping SOV", "output_format": "AirModeler", "scrubbed_filename": "Acme Corp 2026-02-AirModeler.xlsm", "url": "https://vision.pingintel.com/api/v1/sov/019c7d3e-0001-7abc-9000-abcdef123456/output/Acme%20Corp%202026-02-AirModeler.xlsm" }, { "label": "JSON", "output_format": "JSON", "scrubbed_filename": "Acme Corp 2026-02.json", "url": "https://vision.pingintel.com/api/v1/sov/019c7d3e-0001-7abc-9000-abcdef123456/output/Acme%20Corp%202026-02.json" } ] } }, "...", ] } ``` -------------------------------- ### JSON: Example Response Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Truncated example response from the List User Teams endpoint, showing an array of team objects with division_uuid, team_uuid, team_name, and a statuses array containing name and uuid pairs. ```json [ { "division_uuid": "12345678-abc1-cde2-efg3-123456789abcd", "team_uuid": "9876543-abc1-cde2-efg3-123456789abcd", "team_name": "Ping Intel", "statuses": [ { "name": "Received", "uuid": "019c6d26-4468-7b89-8328-d840dc9b5e3b", "...": "..." }, { "name": "Cleared", "uuid": "019c6d26-4e1b-7c89-ab12-d840dc9b5e3c", "...": "..." }, { "name": "Data Entry", "uuid": "019c6d26-4e21-784d-bd26-9d7d70991d91", "...": "..." }, { "name": "Underwriting", "uuid": "019c6d26-4e24-73d5-a2f0-ac50f422ba51", "...": "..." }, "..." ], "...": "..." } ] ``` -------------------------------- ### Update Submission to Simulate Certification (Demo Only) - Python and cURL Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage These demo-only examples show how to set is_building_data_ready=True to simulate Ping's certification step for staging/testing. In production, Ping's backend sets this automatically. The Python function updates any submission attribute, while the cURL command directly patches the submission with the building data ready flag. ```python def update_submission(base_url: str, headers: dict, pingid: str, attr_to_update: str, value): """ Update an attribute of the submission. This calls the Update Submission Details endpoint to modify attributes of a submission. In this demo, we use it to set is_building_data_ready=True to simulate Ping's certification step. In production, Ping's backend would set this automatically when certification completes. """ update_submission_url = f"{base_url}/submission/{pingid}" response = requests.patch( update_submission_url, json={attr_to_update: value}, headers=headers, ) if response.status_code not in (200, 201): raise RuntimeError(f"Failed to update submission: {response.status_code}") # [DEMO ONLY] Mark building data as ready to trigger RUN_OUTPUTTERS # In production, this is set automatically when Ping completes correcting the data update_submission(BASE_URL, headers, pingid, attr_to_update="is_building_data_ready", value=True) ``` ```shell # [DEMO ONLY] Mark building data as ready curl --request PATCH \ --url "https://vision.pingintel.com/api/v1/submission/{id}" \ --header "Authorization: Token " \ --header "Content-Type: application/json" \ --data '{"is_building_data_ready": true}' ``` -------------------------------- ### Change Submission Status - Example Response Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Example JSON response returned by the change_status endpoint when the status transition is successful. The response contains a 'status' field with the value 'success'. ```json { "status": "success" } ``` -------------------------------- ### Run Full Clearance Workflow Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Main entry point that executes the full clearance workflow for a single .eml submission. It resolves team/division, uploads the .eml, starts background monitoring, and polls for statuses. ```python def run_clearance_workflow( *, eml_path: str, company_name: str, team_name: str, api_url: str = "http://localhost:8002/api/v1", auth_token: str | None = None, ) -> str: """ Execute the full clearance workflow for a single .eml submission. This is the main entry point. It performs the following steps: 1. Resolves the team and division from Ping.Vision. 2. Uploads the .eml file as a new submission (USER ACTION). 3. Starts a background thread to monitor events — SSC and OC (USER ACTION). 4. Waits for "Pending Clearance", advances to "Cleared" and "Data Entry" (PING). 5. Ping prepares data for underwriting (PING - demo simplifies via Update Submission API). 6. Waits for "Underwriting" status (USER ACTION polling). 7-8. Background poller listens for OC events and downloads outputs automatically. Returns the pingid of the created submission. """ # Setup API authentication and base URL headers, base_url = authenticate(api_url, auth_token) # ========================================================================== # Step 1: Get Team and Statuses # ========================================================================== print(color_text("Step 1: Looking up team and workflow statuses...", "yellow")) team = get_team(base_url, headers, company_name, team_name) team_uuid = team["team_uuid"] division_uuid = team["division_uuid"] print(f" Team: {team['team_name']} ({team_uuid})") status_uuids = get_statuses(base_url, headers, division_uuid) print(f" Found {len(status_uuids)} workflow statuses") # ========================================================================== # Step 2: Create Submission # ========================================================================== # USER ACTION: A broker or underwriter uploads a submission (e.g., an email # with SOV attachment) to Ping.Vision for processing. This kicks off the # automated intake and clearance workflow. # ========================================================================== print(color_text("\nStep 2: Creating submission...", "yellow")) pingid = create_submission(base_url, headers, team_uuid, eml_path) print(color_text(f" Created submission: {pingid}", "green")) ``` -------------------------------- ### cURL Download Command for Output Files Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Shell command to download an output file using the URL from the OC event metadata. Uses curl with a GET request, authorization token header, and specifies the output filename. ```shell # Download using the URL from the OC event metadata: curl --request GET \ --url "https://vision.pingintel.com/api/v1/sov/{sudid}/output/{filename}" \ --header "Token: " \ --output "{filename}" ``` -------------------------------- ### Change Submission Status - Python and cURL Source: https://docs.pingintel.com/workflows/ping-vision/clear-and-triage Use these examples to programmatically advance a submission through workflow stages (e.g., to 'Cleared' or 'Data Entry') via the change_status endpoint. The Python function raises a RuntimeError on non-2xx responses. The cURL commands show how to transition to 'Cleared' and 'Data Entry' by providing the appropriate workflow_status_uuid. ```python def change_status(base_url: str, headers: dict, pingid: str, new_status_uuid: str): """ Change the workflow status of a submission. Calls the change_status endpoint to transition the submission to a new workflow stage. Use this to programmatically advance submissions through clearance, data entry, underwriting, etc. """ change_status_url = f"{base_url}/submission/{pingid}/change_status" response = requests.patch( change_status_url, json={"workflow_status_uuid": new_status_uuid}, headers=headers, ) if response.status_code not in (200, 201): raise RuntimeError(f"Failed to change status: {response.status_code}") ``` ```shell # Transition to "Cleared" curl --request PATCH \ --url "https://vision.pingintel.com/api/v1/submission/{id}/change_status" \ --header "Authorization: Token " \ --header "Content-Type: application/json" \ --data '{"workflow_status_uuid": ""}' # Transition to "Data Entry" curl --request PATCH \ --url "https://vision.pingintel.com/api/v1/submission/{id}/change_status" \ --header "Authorization: Token " \ --header "Content-Type: application/json" \ --data '{"workflow_status_uuid": ""}' ``` -------------------------------- ### OpenAPI Specification for Get Coverage Option Endpoint Source: https://docs.pingintel.com/ping-vision/cat-modeling/get-coverage-option OpenAPI 3.0.3 specification for the GET /api/v1/submission/{pingid}/cat/coverage-options/{coverage_option_uuid} endpoint. It defines the API server URLs, security, tags, and the response schema with an example response. ```yaml openapi: 3.0.3 info: title: Ping.Vision API version: v1.0 description: > ### Ping.Vision API This API provides convenient, efficient access to Ping Intel's data and services. It is designed to be used by developers and data scientists to integrate Ping Intel's capabilities into their applications. Once SSO is set up with your organization, you can create an Organization or Personal API key at https://auth.pingintel.com/org. Please see the Python client library [pingintel-api](https://pypi.org/project/pingintel-api/) for commandline tools and programmatic access, and you can refer to the following documentation for details on interacting with the system via the HTTP API. contact: email: support@pingintel.com name: Ping Intel url: https://www.pingintel.com servers: - url: https://vision.pingintel.com description: Ping.Vision API - url: https://vision.staging.pingintel.com description: Ping.Vision API (staging) security: [] tags: - name: Create Submission description: The Create Submission API allows you to add new data into the system. - name: Update Submission description: >- The Update Submission API provides various endpoints to update, modify, or act upon existing submissions. - name: Get Submission Data description: '' - name: User Memberships description: >- The User Memberships API allows you to add, remove, and change the role of users in different teams, divisions, or companies. - name: Miscellaneous description: '' paths: /api/v1/submission/{pingid}/cat/coverage-options/{coverage_option_uuid}: get: tags: - CAT Modeling summary: Get Coverage Option description: >- Returns the raw, editable term structure for a coverage option: its peril sections, peril groups (with their subperils), and per-zone terms, along with the `policy_terms_config` that controls which of those term fields are editable/visible for this coverage option's outputter. operationId: api_v1_submission_cat_coverage_options_retrieve_2 parameters: - in: path name: coverage_option_uuid schema: type: string required: true - in: path name: pingid schema: type: string required: true responses: '200': content: application/json: schema: $ref: '#/components/schemas/CoverageOptionDetail' examples: Example: value: uuid: 019dd58e-eb2a-7958-8070-570003e4ee29 name: Option 1 created_time: '2026-04-29T02:10:34.749499Z' modified_time: '2026-04-29T02:10:34.803551Z' bi_limit_type: GE default_bi_period_days: null policy_terms_config: name: PingTest version: 12 allow_peril_sublimits: true allow_peril_min_deductibles: true allow_peril_max_deductibles: true allow_peril_blanket_deductibles: false allow_peril_per_location_deductibles: true allow_peril_bi_deductibles: true allow_zone_sublimits: true allow_zone_min_deductibles: true allow_peril_self_insured_retentions: true allow_peril_agg_limits: true allow_peril_agg_deductibles: true allow_zone_max_deductibles: true allow_zone_per_location_deductible_type: true allow_zone_per_location_deductibles: true allow_zone_exclusion: true allow_layer_premiums: true allow_terms_bi_coverage_type: true allow_terms_bi_number_of_days: true peril_sections: - uuid: 019dd58e-eb2a-7958-8070-570003e4ee50 name: Earthquake peril_groups: - uuid: 019dd58e-eb2a-7958-8070-570003e4ee51 ``` -------------------------------- ### Go example for removing coverage options Source: https://docs.pingintel.com/ping-vision/cat-modeling/modeling-option--remove-layer Creates an HTTP POST request with a JSON body and headers, sends it, and prints the response body. Uses the net/http and io packages. ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://vision.pingintel.com/api/v1/submission/{pingid}/cat/modeling-options/layers/{layer_uuid}/remove-coverage-options" payload := strings.NewReader("{\n \"coverage_option_uuids\": [\n \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n ]\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("Authorization", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(string(body)) } ``` -------------------------------- ### OpenAPI specification for GET /api/v1/usage Source: https://docs.pingintel.com/ping-data/usage/get-usage YAML OpenAPI 3.0.3 specification for the Ping.Data API, including the /api/v1/usage GET endpoint. It also contains embedded JSON examples for the bulk enhance request and output, but these are part of the OpenAPI description. ```yaml openapi: 3.0.3 info: title: Ping.Data API version: v1.0 description: > ### Ping.Data API This API provides convenient, efficient access to bulk location data from many sources. The typical usage flow is: * POST to `/api/v1/bulk_enhance`. The POST body should look like this: ``` { "locations": [ { "id": "user-id1", "address": "1212 Ping Data Lane, Pingville, FL", "sources": ["PG", "PH"], ... }, ... ], "timeout": 60.0, } ``` * Poll GET `/api/v1/bulk_enhance/{id}`, passing the `id` given by the previous response until `response.request.status` is `COMPLETE` or `FAILED`. * Download the data as JSON from `/api/v1/sov/{id}/output/{filename}`. The exact url comes from the response to the above query, in `response.result.outputs[].url`. Output JSON Example: ``` { "user-id1": { "GG": { "is_success": true, "error_message": null, "confidence": 80, "status_code": 200, "fetch_time": 4.754, "street_number": "1212", "route": "Ping Data Ln", "location_type": "ROOFTOP", "latitude": 28.xxx, "longitude": -81.xxx, "formatted_address": "1212 Ping Data Lane, Pingville, FL, USA", "place_id": "xxx-yyy", "address_line_1": "1212 Ping Data Lane", "address_line_2": "", "city": "Pingville", "postal_code": "00010", "county": "Pingville", "state": "FL", "country": "US" }, "HH": { "is_success": true, "error_message": null, "status_code": null, "latitude": 28.xxx, "longitude": -81.xxx, "geocode_type": "ADDRESS", "google_maps_link": "https://www.google.com/maps/search/?api=1&query=28.xxx,-81.xxx", "fema_flood_zone": "X", "elevation": null, "bldg_year_built": 2009, ... more attributes ... } }, ... more buildings ... } ``` contact: email: support@pingintel.com name: Ping Intel url: https://www.pingintel.com servers: - url: https://data-api.sovfixer.com description: Ping.Data API - url: https://data-api-staging.sovfixer.com description: Ping.Data API (staging) security: [] paths: /api/v1/usage: get: tags: - Usage summary: Get Usage description: >- Returns API credit usage over a time range, broken down by data source and time bucket. Each bucket contains a `counts` map of `source -> locations_reserved + locations_used` — credits tied up (reserved in-flight or consumed) in that interval. The `total` key in `counts` (and in `totals`) carries the cross-source aggregate. ``` -------------------------------- ### Python: Request and download SOV output using get_or_create_output Source: https://docs.pingintel.com/workflows/ping-extraction/get-or-create-output Use this script to request an output for an existing SOV, poll until it's ready, and download the result. Requires the SOVFIXER_AUTH_TOKEN environment variable. The POST returns a request.id used for polling, not the SOVID. The script saves the output to workflow_example_results/ and prints the saved filename. ```python """Demo: request and download an output for an existing SOV. Two IDs are involved. Keep them separate: - SOVID: identifies the parsed SOV, passed in the POST path. - request_id: returned by the POST under request.id, used to poll the GET. """ import os import time import requests BASE_URL = "https://api.sovfixer.com/api/v1" SOVID = "s-no-ping-hggcsk" # SOV ID from a previously completed parsing job OUTPUT_FORMAT = "json" # desired output format, e.g., json or auditor POLL_SECONDS = 3 API_KEY = os.environ.get("SOVFIXER_AUTH_TOKEN") headers = {"Authorization": f"Token {API_KEY}"} # 1. Request the output. If a cached output is available the response # returns COMPLETE immediately. Otherwise, generation begins and we # receive a request.id to poll. start_url = f"{BASE_URL}/sov/{SOVID}/get_or_create_output" payload = {"output_format": OUTPUT_FORMAT, "revision": -1, "overwrite_existing": False} start_json = requests.post(start_url, json=payload, headers=headers).json() request_id = start_json["request"]["id"] # 2. Poll until the output is ready. request_id is the polling ID — not SOVID. check_url = f"{BASE_URL}/sov/get_or_create_output/{request_id}" check_json = start_json while check_json["request"]["status"] not in ("COMPLETE", "FAILED"): time.sleep(POLL_SECONDS) check_json = requests.get(check_url, headers=headers).json() if check_json["request"]["status"] == "FAILED": raise RuntimeError(f"Output generation failed: {check_json}") # 3. Download the file. result.url serves the output in its native format, # so write the response body as binary. result = check_json["result"] download = requests.get(result["url"], headers=headers) os.makedirs("workflow_example_results", exist_ok=True) with open(f"workflow_example_results/{result['scrubbed_filename']}", "wb") as f: f.write(download.content) print(f"saved {result['scrubbed_filename']}") ``` -------------------------------- ### GET /api/v1/datasources/{code} Source: https://docs.pingintel.com/ping-data/usage/get-datasource Retrieves the configuration for a datasource identified by its code. The code is case-insensitive and examples include 'PG', 'PH', and 'DTC'. ```APIDOC ## GET /api/v1/datasources/{code} ### Description Returns a datasource configuration for the requested datasource code. ### Method GET ### Endpoint /api/v1/datasources/{code} ### Parameters #### Path Parameters - **code** (string) - Required - Datasource source code (e.g. 'PG', 'PH', 'DTC'). Case-insensitive. ### Response #### Success Response (200) - **config** (object) - The requested datasource's configuration. - **base_output_fields** (object) - Common output fields shared across all datasources (e.g. error_message, fetch_time, status_code). - **datasource_config_attrs** (array of string) - Datasource-specific configuration attributes. #### Response Example { "config": { "base_output_fields": {}, "datasource_config_attrs": [] } } #### Error Responses - **401** - Unauthorized. Returns an ErrorMessage object. - **403** - Forbidden. Returns an ErrorMessage object. - **404** - Not Found. Returns an ErrorMessage object. ### Error Response Example { "message": "Error description" } ``` -------------------------------- ### Example Output for Download (Python and cURL) Source: https://docs.pingintel.com/workflows/ping-extraction/get-or-create-output Example output from the download step, showing the saved filename. The Python output prints 'saved parse_sov_testfile.json', and the cURL output shows a comment indicating the file was written. ```python saved parse_sov_testfile.json ``` ```shell # file written to parse_sov_testfile.json ```