Skip to main content

Submit Shield de-identifying client SDK — strips PHI locally, validates remotely.

Project description

Submit Shield SDK

De-identify claims locally. Validate remotely. PHI never leaves your network.

The Submit Shield SDK is the client-side half of Submit Shield. It runs inside your clinic's network, strips every HIPAA identifier out of each claim before the claim leaves your machine, and posts only the de-identified payload to the Submit Shield validation API. Verdicts come back and the SDK re-hydrates them locally with your real patient context so your billers see real names in their UI while Submit Shield servers only ever see pseudonyms.

This is not a promise — it's an architectural property. The SDK writes an append-only SHA-256 attestation log on every call proving which bytes went out, and those bytes contain no PHI by construction. Your HIPAA officer can audit the log without ever sharing a single patient record.

Why this exists

Traditional claim scrubbers (Waystar, Optum, FinThrive, Availity) all operate under a Business Associate Agreement because they handle raw PHI. That means every customer signs a BAA, every vendor passes PHI to every downstream system, and every breach notification covers everyone.

Submit Shield instead chose to never receive PHI in the first place. Under 45 CFR §164.514(b) (HIPAA Safe Harbor), health information with the 18 enumerated identifiers removed is not PHI and can be disclosed without authorization. The Submit Shield SDK performs that removal on the customer's side of the wire, so Submit Shield's servers are not a Business Associate for any customer using it.

Install

Pick whichever delivery mode fits your environment:

# Python (Linux, macOS, any Python 3.10+ environment)
pip install submitshield

# Docker (any OS with Docker)
docker pull submitshield/sdk:latest

# Windows (standalone .exe, no Python required)
# Download from https://submitshield.health/downloads/submitshield-setup.exe

Configure

The SDK needs two things:

  1. The Submit Shield API URLhttps://api.submitshield.health
  2. A customer secret — a stable random string (≥32 chars) that you generate once and keep in your infrastructure. This is the HMAC key used to pseudonymize member IDs. It never leaves your network.
# Linux / macOS
export SUBMITSHIELD_API_URL=https://api.submitshield.health
export SUBMITSHIELD_CUSTOMER_SECRET="$(openssl rand -hex 32)"
echo "$SUBMITSHIELD_CUSTOMER_SECRET" > /secure/submitshield.secret

# Windows (PowerShell, as administrator)
[System.Environment]::SetEnvironmentVariable('SUBMITSHIELD_API_URL', 'https://api.submitshield.health', 'Machine')
# For the secret, generate with:
[System.Convert]::ToBase64String((1..32 | ForEach-Object { Get-Random -Maximum 256 }))

Validate a claim

# CSV
submitshield validate patient_claims.csv

# FHIR R4 Bundle
submitshield validate patient_claims.fhir.json

# Canonical Claim JSON
submitshield validate claim.json

# Multiple files at once
submitshield validate *.csv --output verdicts.json

Watch a folder

Drop claim files into a folder and let the SDK process them automatically:

submitshield watch /var/spool/submitshield/inbox

# Or with the Docker image
docker run -d --name submitshield \
  -e SUBMITSHIELD_API_URL=https://api.submitshield.health \
  -e SUBMITSHIELD_CUSTOMER_SECRET="$(cat /secure/submitshield.secret)" \
  -v /var/spool/submitshield/inbox:/inbox \
  -v /var/spool/submitshield/verdicts:/outbox \
  -v /var/submitshield:/var/submitshield \
  submitshield/sdk:latest

Inspect the attestation log

Every de-identification call is logged with two SHA-256 hashes — one over the input, one over the de-identified payload. The log is append-only JSONL so it's compatible with every log-rotation tool.

# Last 20 entries
submitshield attest --last 20

# Raw log (feed it to your SIEM)
cat $SUBMITSHIELD_ATTESTATION_LOG

A typical record:

{
  "timestamp": "2026-04-11T19:04:32.118203+00:00",
  "sdk_version": "0.1.0",
  "hostname": "clinic-workstation-3",
  "pid": 4812,
  "format": "csv_row",
  "original_sha256": "a1b2c3d4e5f60708...",
  "deidentified_sha256": "9f8e7d6c5b4a3928...",
  "pseudonym_count": 1,
  "stripped_fields": [
    "patient_first_name",
    "patient_last_name",
    "patient_zip",
    "patient_dob"
  ],
  "server_url": "https://api.submitshield.health",
  "server_request_id": "req_abc123"
}

What the SDK strips

Safe Harbor requires removing 18 identifiers. The SDK handles each one:

# Identifier How we handle it
1 Names Replaced with REDACTED
2 Geographic subdivisions smaller than state Street/city/zip dropped; state retained for MAC routing
3 Dates (except year) related to the individual DOB reduced to {year}-01-01; DoS optionally shifted
4 Phone numbers Stripped
5 Fax numbers Stripped
6 Email addresses Stripped
7 SSN Stripped
8 Medical record numbers HMAC pseudonym
9 Health plan beneficiary / member numbers HMAC pseudonym
10 Account numbers HMAC pseudonym
11 Certificate / license numbers Stripped
12 Vehicle identifiers Stripped
13 Device identifiers / serial numbers Stripped
14 URLs Stripped
15 IP addresses Stripped
16 Biometric identifiers Not present in claim data
17 Full-face photographs Not present in claim data
18 Any other unique identifying number HMAC if it looks like an identifier column

Provider NPIs are not stripped. NPIs are public data (NPPES is the CMS public registry) and are not HIPAA identifiers for the patient.

Remote updates

The SDK checks GET {api_url}/sdk/version on startup (cached 1 hour) and:

  • Same version: silent.
  • Newer available: prints an upgrade notice; the call proceeds.
  • Current version below minimum supported: refuses to run. This is the kill-switch for critical privacy fixes.

To force an upgrade from the server side:

# Publish a new SDK release
hatch build && hatch publish
docker buildx build -t submitshield/sdk:0.1.1 -t submitshield/sdk:latest --push .

# Then update the API's environment
SUBMITSHIELD_SDK_LATEST_VERSION=0.1.1
SUBMITSHIELD_SDK_MIN_SUPPORTED_VERSION=0.1.1   # forces every client to upgrade

Any customer whose SDK hits /sdk/version after this will get the kill-switch response on their next call.

Questions

  • "What if my internet is down?" The update check is best-effort; a network failure during the check does not block validation. Your SDK will keep running with the last successfully-fetched version metadata until connectivity returns.
  • "Can I use this under a BAA if I want to?" Yes. Set SUBMITSHIELD_DEIDENTIFY=false and the SDK passes PHI through unmodified. Your Submit Shield account must be on the BAA-tier plan for this to be accepted on the server side.
  • "Can I self-host the API?" Yes, at the Enterprise tier. See https://submitshield.health/enterprise.
  • "What happens if the Submit Shield API is down?" The SDK fails fast with a clear error message. The raw claim file is untouched — you can re-run when the API is back.
  • "How do you prove my PHI never left my network?" The attestation log carries the hash of the original input and the hash of the outgoing payload. An auditor can hash any PHI field that was present in the original and confirm that hash appears only in the original_sha256 column and never in the deidentified_sha256 column or the API request logs.

License

Proprietary — Submit Shield customer license. See docs/sdk_license.txt.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

submitshield-0.1.0.tar.gz (33.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

submitshield-0.1.0-py3-none-any.whl (25.7 kB view details)

Uploaded Python 3

File details

Details for the file submitshield-0.1.0.tar.gz.

File metadata

  • Download URL: submitshield-0.1.0.tar.gz
  • Upload date:
  • Size: 33.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for submitshield-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c99af0968d41356f6cfd09a28b49b14f0b716669ab2d8e7b52e70e809a9bc806
MD5 517da25e091c51f98a90bd27b50cd927
BLAKE2b-256 149dc42db11afeef7c2db6e8d73d1ed3417a33b8e8787cf2c805a35bd9468bd4

See more details on using hashes here.

File details

Details for the file submitshield-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: submitshield-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 25.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for submitshield-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a8ac910fb78705ad7a8b01f7dbfaa6642caeced8359e58063a063e53d0a3d865
MD5 473f3ad29f34e2ee2bdd592913af9a76
BLAKE2b-256 7e61291671d6d22bb24be691518277a758b544bae3ca495711ffcda0d0c74806

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page