Skip to main content

Solidarity Tech Tools

PyPI - Latest Version PyPI - Total Downloads PyPI - Monthly Downloads

Build & Publish Python Checks Coverage

An unofficial python library to help you automate solidarity tech (ST).

See the ST api page for more details: https://www.solidarity.tech/reference/

This is still in beta, and there is a bit more work to do. But you can still use this in production if you are bold, and I am safely using it on thousands of records.

Features

The primary benefit of using a library like this is to create tooling around your existing ST universe beyond the existing Automations functionality.

Client

Call python methods to interact with the ST api. You can pass pydantic models and receive pydantic models in return, so you can rely on the response structure.

from solidaritytechtools import STClient, models

with STClient(api_key="...") as client:
    # Perform calls
    users = client.get_users()

    # When passing arguments, you can either pass a Pydantic model (recommended)...
    user_1 = client.create_user(models.UserCreate(
        chapter_id=1, 
        phone_number='4145551234'
    ))

    # ...or a raw dict
    user_2 = client.create_user({
        "chapter_id": 1, 
        "phone_number": "4145551234"
    })

The client also handles rate limiting, honoring Retry-After headers, so you can be confident scripts won't break when rate limited.

Contact Matching

Given a JSON ST contact export and a live ST account, you can find the best matches to link local data to live API users. This is extremely useful for migrating historical data (like notes) from one ST account to another.

from solidaritytechtools import find_best_match

# Returns a mapping of {person_id: ClientUserMatch}
# Behind the scenes, this is using the `solidaritytechtools.client` and `solidaritytechtools.json_export`
matches = find_best_match(
    json_export_file="old_account_export.json",
    api_key="new_account_api_key"
)

for person_id, match in matches.items():
    if match:
        print(f"Export Person {person_id} -> API User {match.user_id} ({match.confidence*100}% confidence)")

Current heuristics use email and phone for high-confidence matching, and name + zip code for lower-confidence fuzzy matching. Please look through the code before using this in production to understand what it's doing.

Email Matching & Bulk User Operations

Common operations like lookups or updating users require individual API calls per operation, which hits ST rate limits. There are limited batch endpoints.

You can load every user once into a cached UserStore for fast local lookups and bulk updates, avoiding one API call per user (and the rate limits that come with it).

from solidaritytechtools import STClient, UserStore, find_matches_emails, set_email_permission

# Map a list of emails -> ST user ids (optionally ignoring "+subaddressing")
matches = find_matches_emails(["a@example.com", "b+promo@example.com"], api_key="...", strip_subaddress=True)

# Or build a reusable, file-cached store and query it locally
store = UserStore.from_api(api_key="...")
user = store.match_email("a@example.com")

# Bulk-set a permission across many users
with STClient(api_key="...") as client:
    set_email_permission(client, matches.values(), permission=False)

Traffic Scoring (yard-sign prioritization) (Currently WI only)

Score contacts by how much traffic passes their home and optionally write the score to a custom user property. You can then then create sorted lists in ST to prioritize who to call to make sure yard signs get the most views.

t includes some logic where freeways are excluded so homes snap to the nearest sign-visible surface street. Supports dry runs and a Members-in-Good-Standing filter.

from solidaritytechtools import add_traffic_data

# Dry run: score Members in Good Standing, write nothing
result = add_traffic_data(api_key="...", members_in_good_standing_only=True, dry_run=True)
for contact in result.scored[:10]:
    print(contact.hash_id, contact.aadt, contact.address)

CSV Tools

When working with VAN or ActionNetwork or other tools, you commonly get a csv export. There is some minor convenience tooling to help make working with this easier.

The csv tools have a convenince function to get the only column with emails. This package can be extended for other types.

from solidaritytechtools.utils.csv_tools import get_emails_from_csv

emails = get_emails_from_csv("contacts.csv")

JSON Export Tools

The library includes tools for validating and parsing Solidarity Tech JSON export files into structured models.

from solidaritytechtools import get_persons_from_json_export

# Load and validate an export file
people = get_persons_from_json_export("export-members-data.json")

for person in people:
    print(f"{person.first_name} {person.last_name} has {len(person.notes)} notes")

Using

  1. Add solidaritytechtools as a dependency via uv add solidaritytechtools, pip install solidaritytechtools, etc
  2. Import the client, models, or functions, like from solidaritytechtools import STClient, models, find_best_match

See the /examples directory for scripts demonstrating usage.

Using Pydantic models provides better type safety and IDE autocompletion, but you can always fall back to a dict if the API spec drifts or a model is missing a field.

If you notice client functions not working as expected, feel free to use raw internal methods like client._get("path") or client._put("path", json=payload) to do what you need, and then submit an issue or a MR.

Contributing

  1. Clone the repo
  2. Install pre-commit hooks (uv run pre-commit install) - If you don't, your changes will likely break CICD.
  3. Start coding and make a MR :)

Please use uv run ty check . to check the type safety of your code before submitting a MR.

Publishing

The maintainer will probably take care of this

  1. uv version --bump patch (or minor, major etc)
  2. uv sync
  3. git add pyproject.toml uv.lock
  4. git commit -m "Release $(uv version)" && git tag v$(uv version --short)
  5. git push origin main --tags

Github workflow will push to pypi.

Metadata

Release files for solidaritytechtools 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for solidaritytechtools 0.3.1
File Size Uploaded Provenance Actions
solidaritytechtools-0.3.1.tar.gz 81.3 kB With provenance Details for solidaritytechtools-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for solidaritytechtools 0.3.1
File Interpreter ABI Platform Actions
solidaritytechtools-0.3.1-py3-none-any.whl Python 3 none any Details for solidaritytechtools-0.3.1-py3-none-any.whl

Total release size: 116.4 kB

Release files / solidaritytechtools-0.3.1.tar.gz

Download URL solidaritytechtools-0.3.1.tar.gz
Size 81.3 kB
Tags Source
SHA-256 checksum
How to use checksums
5b1010e41c92248ffb2c479d11c7a724b7cedbe3fe3e4e812d0769f0d29a71ed
BLAKE2b-256 checksum
How to use checksums
1c679a6f915e29712a97d37d4ee8e1a6833b079bf7f173f5d7e5553947cd7332
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.

Transparency log

Release files / solidaritytechtools-0.3.1-py3-none-any.whl

Download URL solidaritytechtools-0.3.1-py3-none-any.whl
Size 35.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
304250df3316d0143de1026672aec957916944abc38d7da0aa6064b74989589a
BLAKE2b-256 checksum
How to use checksums
56f794ba12615d4d463560d80c2a4d60f7da7b7065775b52da546bc611246cc7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.

Transparency log

Security for solidaritytechtools 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for solidaritytechtools-0.3.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 7, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page