Skip to content
Draft
Show file tree
Hide file tree
Changes from 76 commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
9d2d32a
Sort extras in pyproj
bmos Jul 5, 2026
49ea730
add solidarity-tech extra
bmos Jul 5, 2026
9be850f
Allow passing additional headers to APIConnector
bmos Jul 27, 2026
38201c2
Initial work on SolidarityTech connector
bmos Jul 27, 2026
198df60
Add SolidarityTech initialization tests
bmos Jul 27, 2026
8e9bb73
Ensure api token is saved in connector
bmos Jul 27, 2026
ba2764d
Merge branch 'main' into solidarity-tech
bmos Jul 27, 2026
f80ce20
Add methods for event attendances
bmos Jul 28, 2026
11ff17c
Use numpy.int64 where appropriate
bmos Jul 28, 2026
498740f
Update solidarity_tech_agent_assignments.py
bmos Jul 28, 2026
c364bd8
Add Event RSVP methods
bmos Jul 28, 2026
750645e
Allow passing params directly to _get_resources, to combine with the
bmos Jul 28, 2026
83ba623
Fix test folder name
bmos Jul 28, 2026
ffe00f5
Bump min numpy to 2.2
bmos Jul 28, 2026
c31d440
Adjust dependency versions for more python version coverage
bmos Jul 28, 2026
fad1af3
Bump min numpy for python 3.14
bmos Jul 28, 2026
ff58f33
fix method name in event_rsvps
bmos Jul 29, 2026
010b1a0
Add event sessions methods
bmos Jul 29, 2026
b8bcca1
add event methods
bmos Jul 29, 2026
0882b04
Add field survey urls method
bmos Jul 29, 2026
49d0834
Shorter file names
bmos Jul 29, 2026
bd3bd9c
fix survey url documentation link
bmos Jul 29, 2026
206f5bb
add organizations methods
bmos Jul 29, 2026
e999c89
improve parameter handling with error message
bmos Jul 29, 2026
f74616f
include response with HTTPErrors
bmos Jul 29, 2026
4c9bdca
add pages methods
bmos Jul 29, 2026
04eb650
add phonebank methods
bmos Jul 29, 2026
039c23f
move extra params to params arg of _get_resources
bmos Jul 29, 2026
964f266
improved params combining in base class
bmos Jul 29, 2026
8610a04
fix capitalization in phonebanks
bmos Jul 29, 2026
2fb6dc8
add scheduled calls methods
bmos Jul 29, 2026
e7e6178
add scheduled tasks methods
bmos Jul 29, 2026
efe5452
add task agents methods
bmos Jul 29, 2026
4d1cea5
fix scheduled calls urls
bmos Jul 29, 2026
4d17ba7
fix scheduled task url
bmos Jul 29, 2026
3b493ed
add task assignments methods
bmos Jul 29, 2026
9a7e22f
add team members methods
bmos Jul 29, 2026
9975062
type improvements
bmos Jul 29, 2026
17a58d4
Use shared literals
bmos Jul 29, 2026
76dc032
url fixes
bmos Jul 29, 2026
f652ced
add text blast methods
bmos Jul 29, 2026
8c378bc
add text templates methods
bmos Jul 29, 2026
40138bd
add textbank methods
bmos Jul 29, 2026
6832df7
add texts and user_actions methods
bmos Jul 29, 2026
d8417b2
add apiconnector tests including header init and combination
bmos Jul 30, 2026
0acb283
add user list methods
bmos Jul 30, 2026
2749474
docstrings to imperative mood
bmos Jul 30, 2026
a57760b
fix class name of SolidarityTechUserLists
bmos Jul 30, 2026
a7370f4
add user notes methods
bmos Jul 30, 2026
d2706be
generalize ratelimited_api_connector
bmos Jul 30, 2026
449be4a
improve documentating and typing of _base
bmos Jul 30, 2026
983b6bb
move pyrate to general dependencies
bmos Jul 30, 2026
252844f
add user relationships methods
bmos Jul 30, 2026
b8e06e6
Cast self.api_token as str to avoid warning
bmos Aug 1, 2026
9c3d720
Consolidate status code checks/error handling
bmos Aug 2, 2026
cc8a754
add users methods
bmos Aug 2, 2026
4116e58
include response data when initializing exceptions based on HTTPError
bmos Aug 2, 2026
57c126b
Improved return typing and data handling
bmos Aug 2, 2026
642b73b
Merge branch 'move-coop:main' into solidarity-tech
bmos Aug 2, 2026
335d44b
Revised additional_headers implementation (#55)
bmos Aug 2, 2026
9d9f4bf
ruff format
bmos Aug 2, 2026
24c0325
Updated ratelimited api connector (#56)
bmos Aug 2, 2026
a749f00
add first-pass documentation
bmos Aug 2, 2026
307ae3d
add solidarity tech to docs index
bmos Aug 2, 2026
3a1f7c2
Update env variable name
bmos Aug 2, 2026
e3ac4c2
Improve exceptions
bmos Aug 3, 2026
62cda3b
add SolidarityTech to parsons init
bmos Aug 3, 2026
68b7fcf
improve tests
bmos Aug 3, 2026
03905a0
fix kwarg remapping in get_resources
bmos Aug 3, 2026
32290df
improved testing
bmos Aug 3, 2026
48ca8de
add post tests
bmos Aug 3, 2026
fe8f943
test for params collisison in get_resources
bmos Aug 3, 2026
1b20126
test since datetime conversion in get_resources
bmos Aug 3, 2026
f3d3607
Convert literals to enums and use _add_if_field_not_empty to
bmos Aug 5, 2026
2cc5a8b
Update with latest APIConnector + associated type changes
bmos Aug 6, 2026
3c7f83a
Import from future annotations and utilize TYPE_CHECKING block more
bmos Aug 6, 2026
567c529
Remove APIConnector tests (out of scope here)
bmos Aug 6, 2026
f6f708c
Remove obsolete ratelimited API connector documentation
bmos Aug 6, 2026
1475754
Improve SolidarityTech connector documentation
bmos Aug 6, 2026
9f6ae98
Allow passing a requests.Session through SolidarityTech for advanced
bmos Aug 6, 2026
cfef616
Add additional external links in documentation
bmos Aug 6, 2026
410a6c5
Add exceptions to documentation
bmos Aug 6, 2026
797a95b
Shorter names for enum and base files
bmos Aug 6, 2026
64ff3bb
add enums to documentation
bmos Aug 6, 2026
76032fc
Type fixes in SolidarityTechBase
bmos Aug 7, 2026
61452dd
Document and improve SolidarityTech tests
bmos Aug 7, 2026
5c40049
Updated APIConnector typing
bmos Aug 7, 2026
2262d1a
Merge branch 'main' into solidarity-tech
bmos Aug 24, 2026
cfb9931
cleanup base
bmos Aug 25, 2026
f4263da
Improve tests to handle APIConnector changes
bmos Aug 25, 2026
3044156
remove unecessary pass statement
bmos Aug 27, 2026
e7bbcc0
Docstrings
bmos Aug 27, 2026
dca68d5
move exception text to variable
bmos Aug 27, 2026
cd42317
Don't shadow builtin id
bmos Aug 27, 2026
8c806e5
boolean keyword args
bmos Aug 27, 2026
9358f67
Update ratelimited API connector from #1908
bmos Aug 27, 2026
78f0a15
Create TypedDicts for return data
bmos Aug 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
"psycopg2-binary": ("https://www.psycopg.org/docs/", None),
"pyairtable": ("https://pyairtable.readthedocs.io/en/stable/", None),
"PyGitHub": ("https://pygithub.readthedocs.io/en/latest/", None),
"pyratelimiter": ("https://pyratelimiter.readthedocs.io/en/latest/", None),
"requests-toolbelt": ("https://toolbelt.readthedocs.io/en/stable/", None),
"rich": ("https://rich.readthedocs.io/en/stable/", None),
"simple-salesforce": ("https://simple-salesforce.readthedocs.io/en/latest/", None),
Expand Down
7 changes: 7 additions & 0 deletions docs/framework/utilities.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ OAuth API Connector
:inherited-members:
:members:

Rate-Limited API Connector
==========================

.. automodule:: parsons.utilities.ratelimited_api_connector
:inherited-members:
:members:

SQL Helpers
===========

Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ Indices and tables
sftp
shopify
sisense
solidarity_tech
targetsmart
turbovote
twilio
Expand Down
54 changes: 54 additions & 0 deletions docs/solidarity_tech.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
###############
Solidarity Tech
###############

Overview
========

Solidarity Tech's all-in-one nonprofit CRM includes digital tools like
texting, calling, email & websites for advocacy groups, unions & grassroots organizers.

As of September 2026, the :class:`~parsons.solidarity_tech.solidarity_tech.SolidarityTech` connector supports
all endpoints described in the `Solidarity Tech API Documentation <https://www.solidarity.tech/reference/solidarity-tech-api>`_.

Quickstart
==========

To instantiate the :class:`~parsons.solidarity_tech.solidarity_tech.SolidarityTech` class,
you can either store your Solidarity Tech bearer authorization key as
an environmental variable (``SOLIDARITY_TECH_BEARER_KEY``) or pass it as a keyword argument.

.. code-block:: python
:caption: Load bearer authorization key from environment variable

from parsons import SolidarityTech
st = SolidarityTech()

.. code-block:: python
:caption: Pass bearer authorization key as argument

from parsons import SolidarityTech
st = SolidarityTech(api_token='SOME_BEARER_KEY')

You can then call various endpoints:

.. code-block:: python
:caption: Get all events

events = st.get_events()

.. code-block:: python
:caption: Create a new user

st.create_user(
first_name="Elizabeth",
last_name="Flynn",
email="egflynn@example.com"
)

API
====

.. autoclass:: parsons.solidarity_tech.solidarity_tech.SolidarityTech
:inherited-members:
:members:
1 change: 1 addition & 0 deletions parsons/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"SFTP": "parsons.sftp.sftp",
"Shopify": "parsons.shopify.shopify",
"Sisense": "parsons.sisense.sisense",
"SolidarityTech": "parsons.solidarity_tech.solidarity_tech",
"TargetSmartAPI": "parsons.targetsmart.targetsmart_api",
"TargetSmartAutomation": "parsons.targetsmart.targetsmart_automation",
"TurboVote": "parsons.turbovote.turbovote",
Expand Down
3 changes: 3 additions & 0 deletions parsons/solidarity_tech/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from parsons.solidarity_tech.solidarity_tech import SolidarityTech

__all__ = ["SolidarityTech"]
35 changes: 35 additions & 0 deletions parsons/solidarity_tech/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import requests
from requests.exceptions import HTTPError


class STResponseError(HTTPError):
"""Base exception for all Solidarity Tech response errors."""

def __init__(
self, message: str | None = None, *args, err_msg: str, response: requests.Response, **kwargs
) -> None:
if response.status_code:
err_msg += f" (Status Code {response.status_code})"
if message:
err_msg += f" -- {message}"
super().__init__(err_msg, *args, **kwargs)


class STUnexpectedResponseError(STResponseError):
"""Status code is not expected."""

def __init__(
self, message: str | None = None, *args, response: requests.Response, **kwargs
) -> None:
err_msg = "Unexpected Response"
super().__init__(message, *args, err_msg=err_msg, response=response, **kwargs)


class STFailedResponseError(STResponseError):
"""Status code indicates a known failure."""

def __init__(
self, message: str | None = None, *args, response: requests.Response, **kwargs
) -> None:
err_msg = "Request Failed"
super().__init__(message, *args, err_msg=err_msg, response=response, **kwargs)
77 changes: 77 additions & 0 deletions parsons/solidarity_tech/solidarity_tech.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from __future__ import annotations

import logging

from parsons.solidarity_tech.st_activities import SolidarityTechActivities
from parsons.solidarity_tech.st_agent_assignments import SolidarityTechAgentAssignments
from parsons.solidarity_tech.st_automation_enrollments import SolidarityTechAutomationEnrollments
from parsons.solidarity_tech.st_calls import SolidarityTechCalls
from parsons.solidarity_tech.st_chapter_phone_numbers import SolidarityTechChapterPhoneNumbers
from parsons.solidarity_tech.st_chapters import SolidarityTechChapters
from parsons.solidarity_tech.st_custom_user_properties import SolidarityTechCustomUserProperties
from parsons.solidarity_tech.st_donation_charges import SolidarityTechDonationCharges
from parsons.solidarity_tech.st_email_blasts import SolidarityTechEmailBlasts
from parsons.solidarity_tech.st_email_senders import SolidarityTechEmailSenders
from parsons.solidarity_tech.st_emails import SolidarityTechEmails
from parsons.solidarity_tech.st_event_attendances import SolidarityTechEventAttendances
from parsons.solidarity_tech.st_event_rsvps import SolidarityTechEventRSVPs
from parsons.solidarity_tech.st_event_sessions import SolidarityTechEventSessions
from parsons.solidarity_tech.st_events import SolidarityTechEvents
from parsons.solidarity_tech.st_field_survey_urls import SolidarityTechFieldSurveyURLs
from parsons.solidarity_tech.st_organizations import SolidarityTechOrganizations
from parsons.solidarity_tech.st_pages import SolidarityTechPages
from parsons.solidarity_tech.st_phonebanks import SolidarityTechPhonebanks
from parsons.solidarity_tech.st_scheduled_calls import SolidarityTechScheduledCalls
from parsons.solidarity_tech.st_scheduled_tasks import SolidarityTechScheduledTasks
from parsons.solidarity_tech.st_task_agents import SolidarityTechTaskAgents
from parsons.solidarity_tech.st_task_assignments import SolidarityTechTaskAssignments
from parsons.solidarity_tech.st_team_members import SolidarityTechTeamMembers
from parsons.solidarity_tech.st_text_blasts import SolidarityTechTextBlasts
from parsons.solidarity_tech.st_text_templates import SolidarityTechTextTemplates
from parsons.solidarity_tech.st_textbanks import SolidarityTechTextbanks
from parsons.solidarity_tech.st_texts import SolidarityTechTexts
from parsons.solidarity_tech.st_user_actions import SolidarityTechUserActions
from parsons.solidarity_tech.st_user_lists import SolidarityTechUserLists
from parsons.solidarity_tech.st_user_notes import SolidarityTechUserNotes
from parsons.solidarity_tech.st_user_relationships import SolidarityTechUserRelationships
from parsons.solidarity_tech.st_users import SolidarityTechUsers

logger = logging.getLogger(__name__)


class SolidarityTech(
SolidarityTechActivities,
SolidarityTechAgentAssignments,
SolidarityTechAutomationEnrollments,
SolidarityTechCalls,
SolidarityTechChapterPhoneNumbers,
SolidarityTechChapters,
SolidarityTechCustomUserProperties,
SolidarityTechDonationCharges,
SolidarityTechEmailBlasts,
SolidarityTechEmailSenders,
SolidarityTechEmails,
SolidarityTechEventAttendances,
SolidarityTechEventRSVPs,
SolidarityTechEventSessions,
SolidarityTechEvents,
SolidarityTechFieldSurveyURLs,
SolidarityTechOrganizations,
SolidarityTechPages,
SolidarityTechPhonebanks,
SolidarityTechScheduledCalls,
SolidarityTechScheduledTasks,
SolidarityTechTaskAgents,
SolidarityTechTaskAssignments,
SolidarityTechTeamMembers,
SolidarityTechTextBlasts,
SolidarityTechTextTemplates,
SolidarityTechTextbanks,
SolidarityTechTexts,
SolidarityTechUserActions,
SolidarityTechUserLists,
SolidarityTechUserNotes,
SolidarityTechUserRelationships,
SolidarityTechUsers,
):
pass
Loading
Loading