Skip to main content

dotly — SDK oficial de Python para Dotly

Conectá tu sistema con Dotly: contactos y embudo, conversaciones y mensajes de WhatsApp, plantillas, catálogo e inventario, webhooks firmados y Dot AI.

pip install dotly

Python 3.9 o superior. Única dependencia: httpx.

Primeros pasos

  1. En Dotly, entrá a API & SDK → Aplicaciones, creá una aplicación y una clave con los permisos que necesitás. La clave (dtly_live_...) se muestra una sola vez.
  2. Guardala en una variable de entorno, nunca en el código:
export DOTLY_API_KEY="dtly_live_..."
from dotly import Dotly

client = Dotly()  # lee DOTLY_API_KEY

contact = client.contacts.create(phone="595981123456", name="Juan Pérez", tags=["vip"])
client.contacts.update(contact["id"], stage="propuesta", deal_value=2_500_000)

for conversation in client.conversations.iter(status="open"):
    print(conversation["contact"]["name"], conversation["unread_count"])

client.messages.send(to="595981123456", text="¡Hola Juan! Te escribimos de Acme.")

Cada clave actúa en nombre de un integrante de tu equipo: puede, como mucho, lo que esa persona puede en Dotly y ve solo lo que ella ve. Los cambios quedan en la auditoría a su nombre, marcados como hechos por la API.

Cliente asíncrono

import asyncio
from dotly import AsyncDotly

async def main():
    async with AsyncDotly() as client:
        page = await client.contacts.list(limit=50)
        async for message in client.conversations.iter_messages(conversation_id):
            print(message["text"])

asyncio.run(main())

Dotly y AsyncDotly tienen los mismos recursos y métodos.

Recursos

Recurso Métodos Permiso de la clave
client.contacts list, iter, create, get, update, delete, conversations contacts:read, contacts:write, contacts:delete
client.tags list, create (con color) contacts:read, contacts:write
client.conversations list, iter, get, update, set_labels, messages, iter_messages, send_message conversations:read, conversations:write, contacts:write, messages:send
client.messages send, get, edit, delete (para todos), react messages:send, conversations:read
client.groups preview_invite, join, import_all, reset conversations:write
client.templates list, get, flow (menús y submenús), render templates:read
client.members, client.teams, client.whatsapp_accounts list team:read
client.scheduled_messages list, create, cancel conversations:read, messages:send
client.automations list, runs automations:read
client.stats get analytics:read
client.account get account:read
client.events list, iter events:read
client.webhooks list, create, get, update, delete, test, rotate_secret webhooks:manage
client.ai suggest_reply, summarize, rewrite, translate, usage ai:use
client.integration (= client.catalog) ver abajo contacts:write, catalog:read, catalog:write
client.embed_sessions create, list, get, revoke embed:sessions

Las listas devuelven una Page (data, has_more, next_cursor); iter(...) recorre todas las páginas.

Conector de integración (CRM, ERP, tienda)

Tu sistema manda sus datos identificados por su id (external_id). Repetir un upsert es seguro.

client.integration.contacts.upsert("crm-1042", {
    "name": "Juan Pérez",
    "phone": "595981123456",
    "company": "Acme",
    "source_updated_at": "2026-10-19T14:03:00Z",   # descarta cambios más viejos que lleguen tarde
})

client.integration.items.upsert("SKU-1042", {"name": "Zapatilla Runner", "price": 450000, "track_stock": True, "stock": 25})
client.integration.inventory.set("SKU-1042", 24)

results = client.integration.contacts.batch([
    {"external_id": "crm-1", "data": {"phone": "595981000001", "name": "Ana"}},
    {"external_id": "crm-2", "data": {"phone": "595981000002", "name": "Luis"}},
])
failed = [r for r in results["data"] if "error" in r]   # las demás se aplicaron igual
  • Un contacto que ya escribió por WhatsApp se vincula por teléfono, sin duplicarlo.
  • Lo que no enviás queda como está en Dotly (la etapa o las etiquetas que cambió tu equipo no se pisan).
  • Sincronización completa del catálogo: sync_runs.start(), upserts con run_id=... y sync_runs.complete(run_id, missing="deactivate"). Nunca toca contactos.

Dotly dentro de tu sistema (embebido)

session = client.embed_sessions.create(origin="https://crm.tuempresa.com", modules=["inbox", "contacts"],
                                       member_email="ana@tuempresa.com", theme={"accent": "#ff6600", "radius": 8})
# session["url"]: una sola vez y vence en 2 minutos. Mostrala en un <iframe> o con dotly-sdk/embed (navegador).

El dominio y los módulos se autorizan en Dotly (API & SDK). Dotly se abre con los permisos de esa persona recortados a los módulos pedidos, y solo se deja mostrar en ese dominio.

Webhooks

from dotly.webhooks import construct_event, WebhookVerificationError

event = construct_event(raw_body, request.headers.get("Dotly-Signature"), secret)
  • Verificá siempre con el cuerpo crudo (bytes), antes de parsear el JSON.
  • Se rechazan firmas inválidas y marcas de tiempo de más de 5 minutos (repeticiones).
  • Las entregas son "al menos una vez": guardá event["id"] y descartá los repetidos.
  • Ejemplos completos con Flask y FastAPI en examples/.

Dot AI

suggestion = client.ai.suggest_reply(conversation_id)
print(suggestion["data"]["text"])

Dotly verifica todo en el servidor antes de gastar: suscripción, plan, créditos (aparta el costo máximo y cobra el real) y los límites de la persona. Si algo falta, recibís una excepción específica (InsufficientCreditsError, SubscriptionInactiveError, AILimitReachedError, AIUnavailableError...). El SDK no calcula ni guarda saldos.

Errores y reintentos

Todas las excepciones heredan de dotly.DotlyError y traen status, code, message, details y request_id (dáselo a soporte si necesitás ayuda).

El SDK reintenta solo lo que es seguro: lecturas y escrituras con Idempotency-Key. Cada escritura lleva una clave única (la misma en sus reintentos), así un reintento nunca duplica un envío ni cobra dos veces Dot AI. Reintenta errores de red, timeouts, 429 (respetando Retry-After) y 5xx. Podés pasar tu propia clave con idempotency_key=... (por ejemplo, el id del pedido en tu sistema).

Configuración

Dotly(
    api_key="dtly_live_...",      # o DOTLY_API_KEY
    timeout=30,                   # segundos
    max_retries=2,
    app_info="mi-crm/2.3",        # se suma al User-Agent (diagnóstico)
)

La URL base es la de Dotly. Una URL propia tiene que ser https y, si no es de dotly.com.py, hay que permitirla con allow_custom_base_url=True: así una configuración manipulada no envía tu clave a otro servidor.

Versiones

  • El SDK sigue versionado semántico. 0.x: la API v1 está estable; el SDK todavía puede ajustar nombres de métodos en versiones menores (se avisa en el CHANGELOG).
  • dotly.API_VERSION dice para qué versión de la API está hecho ("1"). La API suma campos sin cambiar de versión: leé lo opcional con .get(...).

Licencia MIT.

Metadata

Release files for dotly 0.1.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 dotly 0.1.1
File Size Uploaded Provenance
dotly-0.1.1.tar.gz 29.1 kB With provenance Details

Built distribution (wheel)

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

Total release size: 61.6 kB

Release files / dotly-0.1.1.tar.gz

Download URL dotly-0.1.1.tar.gz
Size 29.1 kB
Tags Source
SHA-256 checksum
How to use checksums
534d5eda98d812adaf21a8e5ebff98ee1bb569dd85db4c9ebbbdcdde1ac6f717
BLAKE2b-256 checksum
How to use checksums
e8b3a9dd4b6c9e2b2d68e63b43eab18e9c1c812dc7e7b8a9d6ab161d240caf3b
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 Oct 21, 2026.

Transparency log

Release files / dotly-0.1.1-py3-none-any.whl

Download URL dotly-0.1.1-py3-none-any.whl
Size 32.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0acc8ba6cc4e3c7e339ad8a7bab6ebbf9d595fe97e4c1d9127740501c32befd7
BLAKE2b-256 checksum
How to use checksums
a7f877a148b87817b8043e99d1ab1befaccb3d7dee8a2fea918769e5416f43c7
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 Oct 21, 2026.

Transparency log

Security for dotly 0.1.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 dotly-0.1.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 Oct 21, 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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files Full provenance

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