### 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
```