Python SDK
The Python SDK provides both synchronous and asynchronous clients with Pydantic models for every request and response.
Install
Section titled “Install”pip install surveycoderRequires Python 3.9+. The async client requires httpx[async], included by default.
Quickstart (sync)
Section titled “Quickstart (sync)”from surveycoder import SurveyCoderimport os
sc = SurveyCoder(api_key=os.environ["SCP_API_KEY"])
result = sc.code( question="Which brand of laundry detergent do you prefer and why?", responses=[ "Tide because it removes stains better", "Ariel - bigger pack, lasts longer", "Persil because my mom always used it", ],)
for entry in result.codebook: print(entry.code, entry.category, entry.count)Quickstart (async)
Section titled “Quickstart (async)”from surveycoder import AsyncSurveyCoderimport asyncioimport os
async def main(): async with AsyncSurveyCoder(api_key=os.environ["SCP_API_KEY"]) as sc: result = await sc.code( question="...", responses=[...], ) print(result.codebook)
asyncio.run(main())AsyncSurveyCoder is a drop-in async equivalent — same method names, same return models, await-able.
Constructor options
Section titled “Constructor options”SurveyCoder( api_key: str, # required base_url: str = "https://api.surveycoder.io", timeout: float = 60.0, max_retries: int = 2, # on 5xx and 429 default_idempotency: str = "auto", # "auto" | "off")Sub-clients
Section titled “Sub-clients”| Sub-client | Endpoint group |
|---|---|
sc.code(...) | POST /v1/code |
sc.projects | Projects and questions CRUD |
sc.jobs | Async job status and waiting |
sc.codebooks | Generate, import, clone, estimate |
sc.quality | Cross-coder consistency |
sc.refinements | Suggestions: list, apply, resolve |
sc.usage | Balance and history |
sc.webhooks | Register and rotate webhooks |
Waiting for async jobs
Section titled “Waiting for async jobs”job = sc.code(question="...", responses=[...]) # 50+ responsesresult = sc.jobs.wait(job.job_id, poll_interval=3.0, timeout=600.0)print(result.codebook)sc.jobs.wait raises SurveyCoderError if the job ends in failed. It honours Retry-After from the server when present.
Errors
Section titled “Errors”from surveycoder import SurveyCoder, SurveyCoderError
try: sc.code(...)except SurveyCoderError as e: print(e.code) # 'INSUFFICIENT_CREDITS' print(e.message) print(e.request_id) # 'req_01HXJZK4...' print(e.doc_url) print(e.status)Every code is documented in the error reference.
Pydantic models
Section titled “Pydantic models”All request and response payloads are Pydantic v2 models, importable from the package root:
from surveycoder import ( CodeRequest, CodeResponse, Codebook, CodedRow,)
req = CodeRequest(question="...", responses=[...])sc.code(**req.model_dump())Webhook signature verification
Section titled “Webhook signature verification”The SDK ships a helper that handles raw-body signing and timing-safe comparison:
from surveycoder import verify_webhookfrom fastapi import FastAPI, Request, HTTPExceptionimport os
app = FastAPI()SECRET = os.environ["SCP_WEBHOOK_SECRET"]
@app.post("/hooks/surveycoder")async def hook(request: Request): body = await request.body() if not verify_webhook(body, request.headers.get("x-sc-signature"), SECRET): raise HTTPException(status_code=401) # ... handle eventRelated
Section titled “Related”- TypeScript SDK — same API surface
- Webhooks
- API reference