Metadata-Version: 2.4
Name: synquic-slide
Version: 0.2.0
Summary: Official Python SDK for the Slide API
Project-URL: Homepage, https://slide.synquic.com
Project-URL: Documentation, https://slide.synquic.com
Author-email: Synquic <p@synquic.com>
License: MIT
Keywords: api,crm,email,otp,rcs,sdk,slide,sms,synquic,voice,whatsapp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27.0
Description-Content-Type: text/markdown

# synquic-slide

**Official Python SDK for the [Slide](https://slide.synquic.com) API**

[![PyPI version](https://img.shields.io/pypi/v/synquic-slide)](https://pypi.org/project/synquic-slide/)
[![Python](https://img.shields.io/pypi/pyversions/synquic-slide)](https://pypi.org/project/synquic-slide/)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)

Slide is a multichannel customer engagement platform. Use this SDK to send WhatsApp messages, SMS, RCS, and OTPs, trigger emails, place AI voice calls, manage contacts, query Shopify orders, and more.

Supports both **sync** and **async** usage. Fully typed with Python type hints.

---

## Installation

```bash
pip install synquic-slide
```

Requires **Python 3.9+**.

---

## Getting Your API Key

1. Log in to your [Slide dashboard](https://slide.synquic.com)
2. Go to **Settings → API Keys**
3. Click **Create API Key**
4. Select the scopes you need (e.g. `email:send`, `whatsapp:send`, `voice:calls:write`)
5. Copy the key — it starts with `sk_live_` and is shown **only once**

```bash
# .env
SLIDE_API_KEY=sk_live_your_key_here
```

---

## Quick Start

```python
import os
from synquic_slide import SlideClient

slide = SlideClient(api_key=os.environ["SLIDE_API_KEY"])

# Send a WhatsApp template
msg = slide.whatsapp.send_template(
    to="+919876543210",
    template_name="order_shipped",
    language_code="en",
)
print(msg["wamid"])

# Send a transactional email
slide.email.send(
    recipient={"to": "customer@example.com", "firstName": "Priya"},
    template_id="tmpl_order_confirm",
    from_name="Acme Store",
    from_email="orders@acme.com",
    variables={"orderId": "#1042", "total": "₹2,499"},
)

# Initiate an outbound AI voice call
call = slide.voice.initiate_outbound_call(
    agent_id="agent_abc123",
    to_number="+919876543210",
    call_context={"customerName": "Priya", "orderId": "#1042"},
)
print(call["id"], call["status"])
```

---

## Async Usage

```python
import asyncio
import os
from synquic_slide import AsyncSlideClient

async def main():
    async with AsyncSlideClient(api_key=os.environ["SLIDE_API_KEY"]) as slide:
        contacts = await slide.contacts.list(page=1, limit=50)
        print(contacts["meta"]["total"])

        msg = await slide.whatsapp.send_template(
            to="+919876543210",
            template_name="order_update",
            language_code="en",
        )
        print(msg["wamid"])

asyncio.run(main())
```

---

## Resources

### Contacts

```python
# List contacts
result = slide.contacts.list(page=1, limit=50, search="priya")
result["data"]         # list of contacts
result["meta"]["total"]
```

**Scope:** `contacts:read`

---

### Email

```python
# Send an email
slide.email.send(
    recipient={"to": "user@example.com", "firstName": "Rahul"},
    template_id="tmpl_welcome",
    from_name="Acme",
    from_email="hello@acme.com",
    subject="Welcome!",           # optional override
    reply_to="support@acme.com",  # optional
    variables={"coupon": "SAVE20"},
)

# List templates
templates = slide.email.list_templates()

# Get a template
tmpl = slide.email.get_template("tmpl_welcome")

# List contacts
contacts = slide.email.list_contacts(page=1, search="rahul")

# Create / update a contact
slide.email.upsert_contact(
    email="user@example.com",
    first_name="Rahul",
    phone="+919876543210",
    tags=["vip", "customer"],
    custom_fields={"city": "Mumbai"},
)
```

**Scopes:** `email:send` · `email:templates:read` · `email:contacts:read` · `email:contacts:write`

---

### WhatsApp

```python
# Send a template
sent = slide.whatsapp.send_template(
    to="+919876543210",
    template_name="order_shipped",
    language_code="en",
    components=[
        {
            "type": "body",
            "parameters": [
                {"type": "text", "text": "#1042"},
                {"type": "text", "text": "Delhivery"},
            ],
        }
    ],
)

# Upload header media
with open("banner.jpg", "rb") as f:
    media = slide.whatsapp.upload_header_media(
        file=f.read(),
        filename="banner.jpg",
        mime_type="image/jpeg",
        expected_format="IMAGE",
    )

# Read message logs
logs = slide.whatsapp.list_logs(direction="outbound", status="delivered")

# List templates
templates = slide.whatsapp.list_templates(status="APPROVED", category="UTILITY")

# Fetch a conversation by phone number
convo = slide.whatsapp.get_conversation_by_phone(phone="+919876543210", limit=50)
print(convo["conversationId"], convo["customerName"])

# Campaigns
campaigns = slide.whatsapp.list_campaigns(page=1, limit=20, status="COMPLETED")
campaign  = slide.whatsapp.get_campaign("camp_abc123")
analytics = slide.whatsapp.get_campaign_analytics("camp_abc123")

created = slide.whatsapp.create_campaign(
    name="Diwali Blast",
    template_id="tmpl_diwali",
    phones=["+919876543210", "+919876543211"],
    variable_mapping={"1": "firstName"},
    scheduled_at="2024-11-01T10:00:00Z",
    schedule_timezone="Asia/Kolkata",
)
slide.whatsapp.launch_campaign(created["id"])
slide.whatsapp.cancel_campaign(created["id"])
```

**Scopes:** `whatsapp:send` · `whatsapp:logs:read` · `whatsapp:templates:read` · `whatsapp:campaigns:read` · `whatsapp:campaigns:write`

---

### SMS

```python
# Send an SMS to one or more recipients
sent = slide.sms.send(
    sender_id="ACMEIN",
    to=["+919876543210", "+919876543211"],
    message="Your order #1042 has shipped!",
    template_id="tmpl_dlt_123",  # optional (DLT template)
    route="transactional",       # optional
)
print(sent["status"], sent["recipients"], sent["externalIds"])

# Templates and senders
templates = slide.sms.list_templates(page=1, limit=50, status="APPROVED")
senders   = slide.sms.list_senders()

# Campaigns
campaigns = slide.sms.list_campaigns(page=1, limit=20)
campaign  = slide.sms.get_campaign("camp_abc123")

created = slide.sms.create_campaign(
    name="Flash Sale",
    message_body="50% off today only! Shop now.",
    sender_id="ACMEIN",
    template_id="tmpl_dlt_456",
    route="promotional",
    audience_type="ALL_CONTACTS",
    scheduled_at="2024-11-01T10:00:00Z",
)
slide.sms.launch_campaign(created["id"])   # {"status": "queued", "campaignId": ...}
slide.sms.cancel_campaign(created["id"])   # {"success": True, "campaignId": ...}

# Logs and stats
logs  = slide.sms.list_logs(direction="outbound", status="delivered")
stats = slide.sms.get_stats(start="2024-01-01", end="2024-01-31")
print(stats["totals"])
```

**Scopes:** `sms:send` · `sms:templates:read` · `sms:campaigns:read` · `sms:campaigns:write` · `sms:logs:read`

---

### RCS

```python
# Send an RCS message with SMS fallback
sent = slide.rcs.send(
    to="+919876543210",
    template_id="tmpl_rcs_promo",
    rcs_variables={"name": "Priya"},
    sms_fallback={
        "sender": "ACMEIN",
        "message": "Check out our new collection!",
        "templateId": "tmpl_dlt_789",
        "route": "promotional",
    },
    ttl=3600,
)

# Bots and templates
bots      = slide.rcs.list_bots()
templates = slide.rcs.list_templates(page=1, limit=50)

# Campaigns
created = slide.rcs.send_campaign(
    bot_id="bot_abc123",
    template_id="tmpl_rcs_promo",
    campaign_name="New Collection Launch",
    numbers=["+919876543210", "+919876543211"],
    country="IN",
    remove_duplicate=True,
    fallback=True,
    fallback_message="Check out our new collection!",
)
campaigns = slide.rcs.list_campaigns(page=1, limit=20)

# Logs and stats
logs  = slide.rcs.list_logs(page=1, limit=50)
stats = slide.rcs.get_stats(start="2024-01-01", end="2024-01-31")
```

**Scopes:** `rcs:send` · `rcs:templates:read` · `rcs:campaigns:read` · `rcs:campaigns:write` · `rcs:logs:read`

---

### OTP

```python
# Send an OTP via a widget
sent = slide.otp.send(widget_id="wgt_abc123", identifier="+919876543210")
request_id = sent["requestId"]

# Retry on another channel
slide.otp.retry(request_id=request_id, channel="sms")

# Verify the OTP entered by the user
verified = slide.otp.verify(request_id=request_id, otp="123456")
access_token = verified["accessToken"]

# Server-side token verification
check = slide.otp.verify_token(access_token=access_token)
print(check["verified"], check["identifier"], check["verifiedAt"])

# Logs and analytics
logs      = slide.otp.list_logs(widget_id="wgt_abc123", status="VERIFIED")
analytics = slide.otp.get_analytics(widget_id="wgt_abc123")
```

**Scopes:** `otp:send` · `otp:verify` · `otp:logs:read`

---

### Instagram

```python
profile = slide.instagram.get_profile()
convos  = slide.instagram.list_conversations(page=1, limit=20)

slide.instagram.send_message(
    recipient_igsid="123456789",
    message="Thanks for reaching out!",
)

insights = slide.instagram.get_insights(period="day", since="2024-01-01", until="2024-01-31")
```

**Scopes:** `instagram:messages:read` · `instagram:messages:send` · `instagram:insights:read`

---

### Shopify

```python
results     = slide.shopify.search_products(q="running shoes", limit=10)
types       = slide.shopify.get_product_types()
product     = slide.shopify.get_product("gid://shopify/Product/123")
collections = slide.shopify.list_collections()
items       = slide.shopify.get_collection_products("col_789", limit=50)
order       = slide.shopify.get_order_status(identifier="#1042")
history     = slide.shopify.get_customer_orders(identifier="+919876543210")
discount    = slide.shopify.validate_discount(code="SAVE20")
```

**Scopes:** `shopify:products:read` · `shopify:orders:read` · `shopify:discounts:read`

---

### Voice

```python
agents    = slide.voice.list_agents()
agent     = slide.voice.get_agent("agent_abc123")

call = slide.voice.initiate_outbound_call(
    agent_id="agent_abc123",
    to_number="+919876543210",
    call_context={"customerName": "Priya"},
)

calls     = slide.voice.list_calls(status="COMPLETED", direction="OUTBOUND")
detail    = slide.voice.get_call("call_xyz")
recording = slide.voice.get_call_recording("call_xyz")  # URL valid 1 hour
analytics = slide.voice.get_analytics(from_date="2024-01-01", to_date="2024-01-31")
```

**Scopes:** `voice:agents:read` · `voice:calls:read` · `voice:calls:write`

---

## Error Handling

```python
from synquic_slide import (
    SlideError,
    SlideAuthError,
    SlideScopeError,
    SlideNotFoundError,
    SlideValidationError,
)

try:
    slide.email.send(...)
except SlideAuthError:
    print("Invalid API key — check SLIDE_API_KEY")
except SlideScopeError as e:
    print(f"Missing scope: {e}")       # e.g. "email:send"
except SlideValidationError as e:
    print(f"Bad request: {e.body}")
except SlideNotFoundError:
    print("Resource not found")
except SlideError as e:
    print(f"HTTP {e.status_code}: {e}")
```

---

## Context Manager

```python
# Sync
with SlideClient(api_key="sk_live_...") as slide:
    slide.contacts.list()

# Async
async with AsyncSlideClient(api_key="sk_live_...") as slide:
    await slide.contacts.list()
```

---

## License

MIT © [Synquic](https://synquic.com)
