custfind
Official Python client for the Custfind API: start lead searches, read scored leads, write and send emails, move deals and receive webhooks. Standard library only; Python 3.9+.
pip install custfind
from custfind import Custfind
cf = Custfind() # reads CUSTFIND_API_KEY
search = cf.searches.create(
sector="Dental clinic",
location="Kadıköy, Istanbul",
limit=25, # caps the credits this search reserves
external_customer_id="acme-42", # optional: bill your own customer
)
cf.searches.wait_for_completion(search["job_id"])
for lead in cf.searches.all_leads(search["job_id"]):
print(lead["name"], lead.get("email"), lead.get("score"))
Safe retries
Every write is sent with an Idempotency-Key that stays the same across retries, and network errors, 429 (respecting Retry-After), 5xx and 409 idempotency_in_progress are retried up to max_retries (3). Any other 409 is final and raised at once. Every write method takes idempotency_key=. A timed-out search is never started twice. Pass your own key to make retries across restarts safe too:
cf.searches.create(idempotency_key=f"search-{order_id}", sector="Dental clinic", location="Izmir", limit=50)
Errors
Failed calls raise CustfindError with .status and the API's .code (api_requires_paid_plan, customer_limit_reached, insufficient_scope, …).
Webhooks
from flask import Flask, request, abort
from custfind import verify_webhook, WebhookVerificationError
@app.post("/webhooks/custfind")
def custfind_webhook():
try:
event = verify_webhook(request.get_data(), request.headers.get("Custfind-Signature"), SECRET)
except WebhookVerificationError:
abort(400)
if event["type"] == "search.completed":
...
return "", 200
Resources
searches, leads, outreach, pipelines, deals, webhooks, customers, sender_accounts, plus me(), balance() and usage(). See the API reference.
Contributing
This repository is a read-only mirror of sdks/python in Custfind's main repository, updated on every release. Issues are welcome here; pull requests are read and ported by hand, then closed, since the next release overwrites this repository.
Developing
python -m unittest discover -s tests -t .
Changelog
- 1.1.0 — Only
409 idempotency_in_progressis retried (a final 409 used to be retried until it gave up). Read timeouts and dropped connections are retried on Python 3.9 too. Every write takesidempotency_key=.searches.leads/all_leadstake every lead filter; newleads.all.outreach.sendtakes an awaredatetime;outreach.rewriteneeds a tone or an instruction. Plain-text error bodies are kept in the message.
Metadata
Release files for custfind 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| custfind-1.1.0.tar.gz | 10.7 kB | With provenance | Details for custfind-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| custfind-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for custfind-1.1.0-py3-none-any.whl |
Total release size: 19.7 kB
Release files / custfind-1.1.0.tar.gz
| Download URL | custfind-1.1.0.tar.gz |
|---|---|
| Size | 10.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
81a31663493e05ef76ee47041acd0dc88ee3df07ede7cd9e38587606ea6e9c07
|
|
BLAKE2b-256 checksum How to use checksums |
66b01066f58e662b7474520eb6587616b36d835f509ef0a6b285fae4259b58c5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 5, 2026.
Transparency logRelease files / custfind-1.1.0-py3-none-any.whl
| Download URL | custfind-1.1.0-py3-none-any.whl |
|---|---|
| Size | 9.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b2e105c371460b1f6ae68f545b4bed531d99c10670113594e1734b002e0379d9
|
|
BLAKE2b-256 checksum How to use checksums |
fd3df457b2434f8f4e488a43a65c3e7f9cf3ad40d2dfcd8ef85554058f5c7ceb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Nov 5, 2026.
Transparency logSecurity for custfind 1.1.0
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.
Attestation for custfind-1.1.0.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 Nov 5, 2026.
Transparency logA 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.