Official Python SDK for Conecto — build chat bots, plugins and integrations on the Conecto customer-messaging platform.
Project description
Conecto for Python
The official Python SDK for Conecto — build chat bots, plugins and integrations on top of a live customer-messaging platform.
pip install conecto
from conecto import Conecto
client = Conecto() # reads CONECTO_CLIENT_ID / CONECTO_SECRET
for convo in client.conversations.list(status="open"):
print(convo.id, convo.preview)
Credentials come from the dashboard: Settings → Developers → new credential. The secret is shown once.
What you can build
1. Automate the workspace
Everything the platform does, driven from your code — conversations, contacts, tickets, help articles, widget configuration, proactive messages.
client.contacts.upsert("maya@acme.io", name="Maya", custom_fields={"plan": "pro"})
client.tickets.create(email="maya@acme.io", message="Card declined", priority="high")
client.visitors.message(
widget_id=7, session=session_id,
body="Your order shipped — want live tracking?",
buttons=["Track my order"],
)
2. Build a bot
A bot is a webhook and a reply. Signature verification, delivery deduplication, event routing and "don't answer your own messages" are handled; you write the part that is yours.
from conecto import Conecto, Bot, blocks
client = Conecto()
bot = Bot(client, secret=WEBHOOK_SECRET)
@bot.on_message
def handle(ctx):
if "refund" in ctx.text.lower():
ctx.reply(
"I can start a refund. Which order?",
buttons=["#1284", "Something else"],
)
elif "how do i reset" in ctx.text.lower():
ctx.reply("Here's how:", blocks=[
blocks.image("https://cdn.you.com/reset.gif", alt="Reset flow"),
blocks.buttons([
blocks.reply_button("That worked"),
blocks.link_button("Full guide", "https://docs.you.com/reset"),
]),
])
else:
ctx.note("Bot didn't recognise this — handing over.")
ctx.handoff()
# Flask
app.add_url_rule("/conecto", view_func=bot.flask_view(), methods=["POST"])
Adapters ship for Flask, FastAPI, Django and bare WSGI.
3. Build a plugin
Declare what your systems can do, and the AI agent calls them mid-conversation. Your store, your billing, your CRM — whatever software they run on.
from conecto import Conecto, Plugin, parameter
plugin = Plugin("acme-store", base_url="https://api.acme.com/conecto")
@plugin.action(
"catalog.search_products", # a reserved name: results become
description="Search the Acme catalog by keyword.", # product cards automatically
parameters=[parameter("query", type="string", required=True)],
)
def search(req):
hits = catalog.search(req.arguments["query"], limit=4)
if not hits:
return req.not_found()
return req.ok(products=[
{"title": p.name, "url": p.url, "image": p.image,
"price_from": f"{p.price:.2f}", "currency": "USD", "available": p.stock > 0}
for p in hits
])
@plugin.action(
"orders.get_status",
risk="verified_read", # refused until identity is proven
description="Status of one of the visitor's own orders.",
parameters=[parameter("order_number", required=True)],
)
def order_status(req):
order = orders.find(req.arguments["order_number"], email=req.verified_email)
return req.ok(**order) if order else req.not_found()
app.add_url_rule("/conecto/<path:action>", view_func=plugin.flask_view(),
methods=["POST"])
plugin.deploy(Conecto()) # idempotent — run it on every release
That is a complete storefront integration. The product cards, the Home showcase and the identity checks come with it.
Rich content
Any message can carry images, GIFs, video, audio, files, embeds, card carousels, label/value lists and buttons.
from conecto import blocks
convo.reply("Here's your order:", blocks=[
blocks.list_block([
blocks.row("Placed", "12 July 2026"),
blocks.row("Status", "Shipped"),
blocks.row("Carrier", "DHL", subtitle="Tracking 4Z8871",
url="https://track.dhl.com/4Z8871"),
], title="Order #1042"),
blocks.cards([
blocks.card("Trail Runner 2", price="89.00 USD", badge="Back in stock",
image="https://cdn.you.com/tr2.jpg",
url="https://shop.you.com/p/tr2",
buttons=[blocks.link_button("Buy", "https://shop.you.com/cart")]),
]),
])
No public URL for that GIF? Upload it:
media = client.media.upload("celebrate.gif")
convo.reply("All set!", blocks=[blocks.image(media)])
Every builder validates locally, so a typo raises BlockError from your line instead
of coming back as an HTTP 400.
Identity
Actions that touch one person's data will not run until we have proven who they are — by an emailed code, or because your site vouched for a logged-in user:
# your backend, right after your own auth check
client.visitors.identify(
widget_id=7, session=conecto_session,
email=user.email, name=user.name,
verified=True, verify_hours=24,
data={"plan": user.plan},
)
# on logout
client.visitors.unverify(widget_id=7, session=conecto_session)
Inside a plugin, req.verified_email is the address we proved. An email in
req.arguments is whatever the model parsed out of a chat — never authorization.
Things that will save you an afternoon
Verify webhooks against the raw body. Re-serializing JSON changes the bytes and the signature stops matching. This is the most common first-integration bug, and the SDK raises a message saying so if you pass a parsed dict.
event = webhooks.parse(request.get_data(), request.headers, secret=SECRET)
Deliveries are at-least-once. Dedupe on event.id, and pass it as your idempotency
key when replying — Bot does both for you.
Pagination iterates itself.
page = client.contacts.list(query="acme")
page.items # this page
for c in page: # every page, fetched lazily
...
page.all() # everything, in one list
Errors are typed.
from conecto import ConversationClosed, RateLimited
try:
convo.reply("Refunded.")
except ConversationClosed:
convo.reopen()
convo.reply("Refunded.")
Retries for timeouts, 429s and 5xx are automatic and honour Retry-After. Writes are
retried safely because every write carries an idempotency key.
Reference
client.conversations |
list, read, reply, typing, handoff, assign, close |
client.contacts |
upsert by email, search, update, delete |
client.visitors |
identify + vouch, unverify, proactive messages |
client.tickets |
create, update, reply, categories |
client.articles |
search and publish help-center content |
client.integrations |
register, install, run and deploy plugins |
client.widgets |
read and update widget configuration |
client.media |
upload files for blocks |
client.webhooks |
subscribe endpoints to events |
client.members |
teammates, for assignment |
client.meta |
me(), schema(), stats() |
client.meta.schema() returns the whole API described as JSON — endpoints, events, block
types, reserved actions and every limit — served by the same code that enforces them.
Requirements: Python 3.9+ and requests.
Documentation: https://conecto.chat/developers · Issues: https://github.com/Nancy-Consulting/conecto-sdk/issues
MIT licensed.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file conecto-0.1.0.tar.gz.
File metadata
- Download URL: conecto-0.1.0.tar.gz
- Upload date:
- Size: 64.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec6dd27b37561d6f2359e431d42ef0bf1122aa74e53b387cf03999ce644d33d8
|
|
| MD5 |
da68af762fa900dd0c9f8f22369ea095
|
|
| BLAKE2b-256 |
4781063ebdc94b6ccb18915d68bbb5cfc065ae88686d3bd377602b0820df81b0
|
File details
Details for the file conecto-0.1.0-py3-none-any.whl.
File metadata
- Download URL: conecto-0.1.0-py3-none-any.whl
- Upload date:
- Size: 58.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a04dcd74b77f6a5949e021312f55b8d21b81cc4e3ac299a1a422a477c467712d
|
|
| MD5 |
9c656b8ff7e5353dc69416ffe16d24b6
|
|
| BLAKE2b-256 |
33ae8abb6631ba08aeae4d88205a8d30fead891953ea66b5b4b9571d1100bbc1
|