add campaign api (#274)
This commit is contained in:
@@ -37,6 +37,29 @@ resp, _ = client.emails.send(payload={
|
||||
"html": "<strong>Hi!</strong>",
|
||||
})
|
||||
|
||||
# 3) Campaigns
|
||||
campaign_payload: types.CampaignCreate = {
|
||||
"name": "Welcome Series",
|
||||
"subject": "Welcome to our service!",
|
||||
"html": "<p>Thanks for joining us!</p>",
|
||||
"from": "welcome@example.com",
|
||||
"contactBookId": "cb_1234567890",
|
||||
}
|
||||
campaign_resp, _ = client.campaigns.create(payload=campaign_payload)
|
||||
|
||||
# Schedule a campaign
|
||||
schedule_payload: types.CampaignSchedule = {
|
||||
"scheduledAt": "2024-12-01T10:00:00Z",
|
||||
}
|
||||
schedule_resp, _ = client.campaigns.schedule(
|
||||
campaign_id=campaign_resp["id"],
|
||||
payload=schedule_payload
|
||||
)
|
||||
|
||||
# Pause/resume campaigns
|
||||
client.campaigns.pause(campaign_id="campaign_123")
|
||||
client.campaigns.resume(campaign_id="campaign_123")
|
||||
|
||||
# Toggle behavior if desired:
|
||||
# - raise_on_error=False: return (None, error_dict) instead of raising
|
||||
# No model parsing occurs; methods return plain dicts following the typed shapes.
|
||||
@@ -55,7 +78,14 @@ This package is managed with Poetry. Models are maintained in-repo under
|
||||
|
||||
It is published as `usesend` on PyPI.
|
||||
|
||||
## Available Resources
|
||||
|
||||
- **Emails**: `client.emails.send()`, `client.emails.get()`
|
||||
- **Contacts**: `client.contacts.create()`, `client.contacts.get()`, `client.contacts.list()`
|
||||
- **Domains**: `client.domains.create()`, `client.domains.get()`, `client.domains.verify()`
|
||||
- **Campaigns**: `client.campaigns.create()`, `client.campaigns.get()`, `client.campaigns.schedule()`, `client.campaigns.pause()`, `client.campaigns.resume()`
|
||||
|
||||
Notes
|
||||
|
||||
- Human-friendly models are available under `usesend.types` (e.g., `EmailCreate`, `Contact`, `APIError`).
|
||||
- Human-friendly models are available under `usesend.types` (e.g., `EmailCreate`, `CampaignCreate`, `Contact`, `APIError`).
|
||||
- Endpoint methods accept TypedDict payloads or plain dicts via the `payload=` keyword.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "usesend"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
description = "Python SDK for the UseSend API"
|
||||
authors = ["UseSend"]
|
||||
license = "MIT"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from .usesend import UseSend, UseSendHTTPError
|
||||
from .domains import Domains # type: ignore
|
||||
from .campaigns import Campaigns # type: ignore
|
||||
from . import types
|
||||
|
||||
__all__ = ["UseSend", "UseSendHTTPError", "types", "Domains"]
|
||||
__all__ = ["UseSend", "UseSendHTTPError", "types", "Domains", "Campaigns"]
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Campaign resource client using TypedDict shapes (no Pydantic)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
|
||||
from .types import (
|
||||
APIError,
|
||||
Campaign,
|
||||
CampaignCreate,
|
||||
CampaignCreateResponse,
|
||||
CampaignSchedule,
|
||||
CampaignScheduleResponse,
|
||||
CampaignActionResponse,
|
||||
)
|
||||
|
||||
|
||||
class Campaigns:
|
||||
"""Client for `/campaigns` endpoints."""
|
||||
|
||||
def __init__(self, usesend: "UseSend") -> None:
|
||||
self.usesend = usesend
|
||||
|
||||
def create(
|
||||
self, payload: CampaignCreate
|
||||
) -> Tuple[Optional[CampaignCreateResponse], Optional[APIError]]:
|
||||
data, err = self.usesend.post(
|
||||
"/campaigns",
|
||||
payload,
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
def get(
|
||||
self, campaign_id: str
|
||||
) -> Tuple[Optional[Campaign], Optional[APIError]]:
|
||||
data, err = self.usesend.get(
|
||||
f"/campaigns/{campaign_id}"
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
def schedule(
|
||||
self, campaign_id: str, payload: CampaignSchedule
|
||||
) -> Tuple[Optional[CampaignScheduleResponse], Optional[APIError]]:
|
||||
data, err = self.usesend.post(
|
||||
f"/campaigns/{campaign_id}/schedule",
|
||||
payload,
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
def pause(
|
||||
self, campaign_id: str
|
||||
) -> Tuple[Optional[CampaignActionResponse], Optional[APIError]]:
|
||||
data, err = self.usesend.post(
|
||||
f"/campaigns/{campaign_id}/pause",
|
||||
{},
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
def resume(
|
||||
self, campaign_id: str
|
||||
) -> Tuple[Optional[CampaignActionResponse], Optional[APIError]]:
|
||||
data, err = self.usesend.post(
|
||||
f"/campaigns/{campaign_id}/resume",
|
||||
{},
|
||||
)
|
||||
return (data, err) # type: ignore[return-value]
|
||||
|
||||
|
||||
from .usesend import UseSend # noqa: E402 pylint: disable=wrong-import-position
|
||||
@@ -15,14 +15,14 @@ from typing_extensions import NotRequired, Required, Literal
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
DomainStatus = Literal[
|
||||
'NOT_STARTED',
|
||||
'PENDING',
|
||||
'SUCCESS',
|
||||
'FAILED',
|
||||
'TEMPORARY_FAILURE',
|
||||
"NOT_STARTED",
|
||||
"PENDING",
|
||||
"SUCCESS",
|
||||
"FAILED",
|
||||
"TEMPORARY_FAILURE",
|
||||
]
|
||||
|
||||
DNSRecordType = Literal['MX', 'TXT']
|
||||
DNSRecordType = Literal["MX", "TXT"]
|
||||
|
||||
|
||||
class DNSRecord(TypedDict, total=False):
|
||||
@@ -99,24 +99,25 @@ class DomainDeleteResponse(TypedDict):
|
||||
success: bool
|
||||
message: str
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Emails
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
EmailEventStatus = Literal[
|
||||
'SCHEDULED',
|
||||
'QUEUED',
|
||||
'SENT',
|
||||
'DELIVERY_DELAYED',
|
||||
'BOUNCED',
|
||||
'REJECTED',
|
||||
'RENDERING_FAILURE',
|
||||
'DELIVERED',
|
||||
'OPENED',
|
||||
'CLICKED',
|
||||
'COMPLAINED',
|
||||
'FAILED',
|
||||
'CANCELLED',
|
||||
"SCHEDULED",
|
||||
"QUEUED",
|
||||
"SENT",
|
||||
"DELIVERY_DELAYED",
|
||||
"BOUNCED",
|
||||
"REJECTED",
|
||||
"RENDERING_FAILURE",
|
||||
"DELIVERED",
|
||||
"OPENED",
|
||||
"CLICKED",
|
||||
"COMPLAINED",
|
||||
"FAILED",
|
||||
"CANCELLED",
|
||||
]
|
||||
|
||||
|
||||
@@ -128,22 +129,22 @@ class EmailEvent(TypedDict, total=False):
|
||||
|
||||
|
||||
Email = TypedDict(
|
||||
'Email',
|
||||
"Email",
|
||||
{
|
||||
'id': str,
|
||||
'teamId': float,
|
||||
'to': Union[str, List[str]],
|
||||
'replyTo': NotRequired[Union[str, List[str]]],
|
||||
'cc': NotRequired[Union[str, List[str]]],
|
||||
'bcc': NotRequired[Union[str, List[str]]],
|
||||
'from': str,
|
||||
'subject': str,
|
||||
'html': str,
|
||||
'text': str,
|
||||
'createdAt': str,
|
||||
'updatedAt': str,
|
||||
'emailEvents': List[EmailEvent],
|
||||
}
|
||||
"id": str,
|
||||
"teamId": float,
|
||||
"to": Union[str, List[str]],
|
||||
"replyTo": NotRequired[Union[str, List[str]]],
|
||||
"cc": NotRequired[Union[str, List[str]]],
|
||||
"bcc": NotRequired[Union[str, List[str]]],
|
||||
"from": str,
|
||||
"subject": str,
|
||||
"html": str,
|
||||
"text": str,
|
||||
"createdAt": str,
|
||||
"updatedAt": str,
|
||||
"emailEvents": List[EmailEvent],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -157,40 +158,40 @@ class EmailUpdateResponse(TypedDict, total=False):
|
||||
|
||||
|
||||
EmailLatestStatus = Literal[
|
||||
'SCHEDULED',
|
||||
'QUEUED',
|
||||
'SENT',
|
||||
'DELIVERY_DELAYED',
|
||||
'BOUNCED',
|
||||
'REJECTED',
|
||||
'RENDERING_FAILURE',
|
||||
'DELIVERED',
|
||||
'OPENED',
|
||||
'CLICKED',
|
||||
'COMPLAINED',
|
||||
'FAILED',
|
||||
'CANCELLED',
|
||||
"SCHEDULED",
|
||||
"QUEUED",
|
||||
"SENT",
|
||||
"DELIVERY_DELAYED",
|
||||
"BOUNCED",
|
||||
"REJECTED",
|
||||
"RENDERING_FAILURE",
|
||||
"DELIVERED",
|
||||
"OPENED",
|
||||
"CLICKED",
|
||||
"COMPLAINED",
|
||||
"FAILED",
|
||||
"CANCELLED",
|
||||
]
|
||||
|
||||
|
||||
EmailListItem = TypedDict(
|
||||
'EmailListItem',
|
||||
"EmailListItem",
|
||||
{
|
||||
'id': str,
|
||||
'to': Union[str, List[str]],
|
||||
'replyTo': NotRequired[Union[str, List[str]]],
|
||||
'cc': NotRequired[Union[str, List[str]]],
|
||||
'bcc': NotRequired[Union[str, List[str]]],
|
||||
'from': str,
|
||||
'subject': str,
|
||||
'html': str,
|
||||
'text': str,
|
||||
'createdAt': str,
|
||||
'updatedAt': str,
|
||||
'latestStatus': EmailLatestStatus,
|
||||
'scheduledAt': str,
|
||||
'domainId': float,
|
||||
}
|
||||
"id": str,
|
||||
"to": Union[str, List[str]],
|
||||
"replyTo": NotRequired[Union[str, List[str]]],
|
||||
"cc": NotRequired[Union[str, List[str]]],
|
||||
"bcc": NotRequired[Union[str, List[str]]],
|
||||
"from": str,
|
||||
"subject": str,
|
||||
"html": str,
|
||||
"text": str,
|
||||
"createdAt": str,
|
||||
"updatedAt": str,
|
||||
"latestStatus": EmailLatestStatus,
|
||||
"scheduledAt": str,
|
||||
"domainId": float,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -205,23 +206,23 @@ class Attachment(TypedDict):
|
||||
|
||||
|
||||
EmailCreate = TypedDict(
|
||||
'EmailCreate',
|
||||
"EmailCreate",
|
||||
{
|
||||
'to': Required[Union[str, List[str]]],
|
||||
'from': Required[str],
|
||||
'subject': NotRequired[str],
|
||||
'templateId': NotRequired[str],
|
||||
'variables': NotRequired[Dict[str, str]],
|
||||
'replyTo': NotRequired[Union[str, List[str]]],
|
||||
'cc': NotRequired[Union[str, List[str]]],
|
||||
'bcc': NotRequired[Union[str, List[str]]],
|
||||
'text': NotRequired[str],
|
||||
'html': NotRequired[str],
|
||||
'attachments': NotRequired[List[Attachment]],
|
||||
'scheduledAt': NotRequired[Union[datetime, str]],
|
||||
'inReplyToId': NotRequired[str],
|
||||
'headers': NotRequired[Dict[str, str]],
|
||||
}
|
||||
"to": Required[Union[str, List[str]]],
|
||||
"from": Required[str],
|
||||
"subject": NotRequired[str],
|
||||
"templateId": NotRequired[str],
|
||||
"variables": NotRequired[Dict[str, str]],
|
||||
"replyTo": NotRequired[Union[str, List[str]]],
|
||||
"cc": NotRequired[Union[str, List[str]]],
|
||||
"bcc": NotRequired[Union[str, List[str]]],
|
||||
"text": NotRequired[str],
|
||||
"html": NotRequired[str],
|
||||
"attachments": NotRequired[List[Attachment]],
|
||||
"scheduledAt": NotRequired[Union[datetime, str]],
|
||||
"inReplyToId": NotRequired[str],
|
||||
"headers": NotRequired[Dict[str, str]],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -230,23 +231,23 @@ class EmailCreateResponse(TypedDict, total=False):
|
||||
|
||||
|
||||
EmailBatchItem = TypedDict(
|
||||
'EmailBatchItem',
|
||||
"EmailBatchItem",
|
||||
{
|
||||
'to': Required[Union[str, List[str]]],
|
||||
'from': Required[str],
|
||||
'subject': NotRequired[str],
|
||||
'templateId': NotRequired[str],
|
||||
'variables': NotRequired[Dict[str, str]],
|
||||
'replyTo': NotRequired[Union[str, List[str]]],
|
||||
'cc': NotRequired[Union[str, List[str]]],
|
||||
'bcc': NotRequired[Union[str, List[str]]],
|
||||
'text': NotRequired[str],
|
||||
'html': NotRequired[str],
|
||||
'attachments': NotRequired[List[Attachment]],
|
||||
'scheduledAt': NotRequired[Union[datetime, str]],
|
||||
'inReplyToId': NotRequired[str],
|
||||
'headers': NotRequired[Dict[str, str]],
|
||||
}
|
||||
"to": Required[Union[str, List[str]]],
|
||||
"from": Required[str],
|
||||
"subject": NotRequired[str],
|
||||
"templateId": NotRequired[str],
|
||||
"variables": NotRequired[Dict[str, str]],
|
||||
"replyTo": NotRequired[Union[str, List[str]]],
|
||||
"cc": NotRequired[Union[str, List[str]]],
|
||||
"bcc": NotRequired[Union[str, List[str]]],
|
||||
"text": NotRequired[str],
|
||||
"html": NotRequired[str],
|
||||
"attachments": NotRequired[List[Attachment]],
|
||||
"scheduledAt": NotRequired[Union[datetime, str]],
|
||||
"inReplyToId": NotRequired[str],
|
||||
"headers": NotRequired[Dict[str, str]],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -269,6 +270,7 @@ class EmailCancelResponse(TypedDict, total=False):
|
||||
# Contacts
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class ContactCreate(TypedDict, total=False):
|
||||
email: str
|
||||
firstName: Optional[str]
|
||||
@@ -335,11 +337,115 @@ class ContactDeleteResponse(TypedDict):
|
||||
success: bool
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Campaigns
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
Campaign = TypedDict(
|
||||
"Campaign",
|
||||
{
|
||||
"id": str,
|
||||
"name": str,
|
||||
"from": str,
|
||||
"subject": str,
|
||||
"previewText": Optional[str],
|
||||
"contactBookId": Optional[str],
|
||||
"html": Optional[str],
|
||||
"content": Optional[str],
|
||||
"status": str,
|
||||
"scheduledAt": Optional[str],
|
||||
"batchSize": int,
|
||||
"batchWindowMinutes": int,
|
||||
"total": int,
|
||||
"sent": int,
|
||||
"delivered": int,
|
||||
"opened": int,
|
||||
"clicked": int,
|
||||
"unsubscribed": int,
|
||||
"bounced": int,
|
||||
"hardBounced": int,
|
||||
"complained": int,
|
||||
"replyTo": List[str],
|
||||
"cc": List[str],
|
||||
"bcc": List[str],
|
||||
"createdAt": str,
|
||||
"updatedAt": str,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
CampaignCreate = TypedDict(
|
||||
"CampaignCreate",
|
||||
{
|
||||
"name": Required[str],
|
||||
"from": Required[str],
|
||||
"subject": Required[str],
|
||||
"previewText": NotRequired[str],
|
||||
"contactBookId": Required[str],
|
||||
"content": NotRequired[str],
|
||||
"html": NotRequired[str],
|
||||
"replyTo": NotRequired[Union[str, List[str]]],
|
||||
"cc": NotRequired[Union[str, List[str]]],
|
||||
"bcc": NotRequired[Union[str, List[str]]],
|
||||
"sendNow": NotRequired[bool],
|
||||
"scheduledAt": NotRequired[str],
|
||||
"batchSize": NotRequired[int],
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
CampaignCreateResponse = TypedDict(
|
||||
"CampaignCreateResponse",
|
||||
{
|
||||
"id": str,
|
||||
"name": str,
|
||||
"from": str,
|
||||
"subject": str,
|
||||
"previewText": Optional[str],
|
||||
"contactBookId": Optional[str],
|
||||
"html": Optional[str],
|
||||
"content": Optional[str],
|
||||
"status": str,
|
||||
"scheduledAt": Optional[str],
|
||||
"batchSize": int,
|
||||
"batchWindowMinutes": int,
|
||||
"total": int,
|
||||
"sent": int,
|
||||
"delivered": int,
|
||||
"opened": int,
|
||||
"clicked": int,
|
||||
"unsubscribed": int,
|
||||
"bounced": int,
|
||||
"hardBounced": int,
|
||||
"complained": int,
|
||||
"replyTo": List[str],
|
||||
"cc": List[str],
|
||||
"bcc": List[str],
|
||||
"createdAt": str,
|
||||
"updatedAt": str,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class CampaignSchedule(TypedDict, total=False):
|
||||
scheduledAt: Optional[str]
|
||||
batchSize: Optional[int]
|
||||
sendNow: Optional[bool]
|
||||
|
||||
|
||||
class CampaignScheduleResponse(TypedDict, total=False):
|
||||
success: bool
|
||||
|
||||
|
||||
class CampaignActionResponse(TypedDict, total=False):
|
||||
success: bool
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Common
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
class APIError(TypedDict):
|
||||
code: str
|
||||
message: str
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ class UseSend:
|
||||
self.emails = Emails(self)
|
||||
self.contacts = Contacts(self)
|
||||
self.domains = Domains(self)
|
||||
self.campaigns = Campaigns(self)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Internal request helper
|
||||
@@ -125,3 +126,4 @@ class UseSend:
|
||||
from .emails import Emails # noqa: E402 pylint: disable=wrong-import-position
|
||||
from .contacts import Contacts # noqa: E402 pylint: disable=wrong-import-position
|
||||
from .domains import Domains # type: ignore # noqa: E402
|
||||
from .campaigns import Campaigns # type: ignore # noqa: E402
|
||||
|
||||
@@ -49,3 +49,38 @@ usesend.emails.send({
|
||||
text: "useSend is the best open source product to send emails",
|
||||
});
|
||||
```
|
||||
|
||||
## Campaigns
|
||||
|
||||
Create and manage email campaigns:
|
||||
|
||||
```javascript
|
||||
import { UseSend } from "usesend";
|
||||
|
||||
const usesend = new UseSend("us_12345");
|
||||
|
||||
// Create a campaign
|
||||
const campaign = await usesend.campaigns.create({
|
||||
name: "Welcome Series",
|
||||
from: "hello@company.com",
|
||||
subject: "Welcome to our platform!",
|
||||
contactBookId: "cb_12345",
|
||||
html: "<h1>Welcome!</h1><p>Thanks for joining us.</p>",
|
||||
sendNow: false,
|
||||
});
|
||||
|
||||
// Schedule a campaign
|
||||
await usesend.campaigns.schedule(campaign.data.id, {
|
||||
scheduledAt: "2024-12-01T09:00:00Z",
|
||||
batchSize: 1000,
|
||||
});
|
||||
|
||||
// Get campaign details
|
||||
const details = await usesend.campaigns.get(campaign.data.id);
|
||||
|
||||
// Pause a campaign
|
||||
await usesend.campaigns.pause(campaign.data.id);
|
||||
|
||||
// Resume a campaign
|
||||
await usesend.campaigns.resume(campaign.data.id);
|
||||
```
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
export { UseSend } from "./src/usesend";
|
||||
export { UseSend as Unsend } from "./src/usesend"; // deprecated alias
|
||||
export { Campaigns } from "./src/campaign";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "usesend-js",
|
||||
"version": "1.5.5",
|
||||
"version": "1.5.6",
|
||||
"description": "",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.mjs",
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import { UseSend } from "./usesend";
|
||||
import { paths } from "../types/schema";
|
||||
import { ErrorResponse } from "../types";
|
||||
|
||||
type CreateCampaignPayload =
|
||||
paths["/v1/campaigns"]["post"]["requestBody"]["content"]["application/json"];
|
||||
|
||||
type CreateCampaignResponse = {
|
||||
data: CreateCampaignResponseSuccess | null;
|
||||
error: ErrorResponse | null;
|
||||
};
|
||||
|
||||
type CreateCampaignResponseSuccess =
|
||||
paths["/v1/campaigns"]["post"]["responses"]["200"]["content"]["application/json"];
|
||||
|
||||
type GetCampaignResponseSuccess =
|
||||
paths["/v1/campaigns/{campaignId}"]["get"]["responses"]["200"]["content"]["application/json"];
|
||||
|
||||
type GetCampaignResponse = {
|
||||
data: GetCampaignResponseSuccess | null;
|
||||
error: ErrorResponse | null;
|
||||
};
|
||||
|
||||
type ScheduleCampaignPayload =
|
||||
paths["/v1/campaigns/{campaignId}/schedule"]["post"]["requestBody"]["content"]["application/json"];
|
||||
|
||||
type ScheduleCampaignResponseSuccess =
|
||||
paths["/v1/campaigns/{campaignId}/schedule"]["post"]["responses"]["200"]["content"]["application/json"];
|
||||
|
||||
type ScheduleCampaignResponse = {
|
||||
data: ScheduleCampaignResponseSuccess | null;
|
||||
error: ErrorResponse | null;
|
||||
};
|
||||
|
||||
type CampaignActionResponseSuccess = { success: boolean };
|
||||
|
||||
type CampaignActionResponse = {
|
||||
data: CampaignActionResponseSuccess | null;
|
||||
error: ErrorResponse | null;
|
||||
};
|
||||
|
||||
export class Campaigns {
|
||||
constructor(private readonly usesend: UseSend) {
|
||||
this.usesend = usesend;
|
||||
}
|
||||
|
||||
async create(
|
||||
payload: CreateCampaignPayload,
|
||||
): Promise<CreateCampaignResponse> {
|
||||
const data = await this.usesend.post<CreateCampaignResponseSuccess>(
|
||||
`/campaigns`,
|
||||
payload,
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async get(campaignId: string): Promise<GetCampaignResponse> {
|
||||
const data = await this.usesend.get<GetCampaignResponseSuccess>(
|
||||
`/campaigns/${campaignId}`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
async schedule(
|
||||
campaignId: string,
|
||||
payload: ScheduleCampaignPayload,
|
||||
): Promise<ScheduleCampaignResponse> {
|
||||
const data = await this.usesend.post<ScheduleCampaignResponseSuccess>(
|
||||
`/campaigns/${campaignId}/schedule`,
|
||||
payload,
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async pause(campaignId: string): Promise<CampaignActionResponse> {
|
||||
const data = await this.usesend.post<CampaignActionResponseSuccess>(
|
||||
`/campaigns/${campaignId}/pause`,
|
||||
{},
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
async resume(campaignId: string): Promise<CampaignActionResponse> {
|
||||
const data = await this.usesend.post<CampaignActionResponseSuccess>(
|
||||
`/campaigns/${campaignId}/resume`,
|
||||
{},
|
||||
);
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { ErrorResponse } from "../types";
|
||||
import { Contacts } from "./contact";
|
||||
import { Emails } from "./email";
|
||||
import { Domains } from "./domain";
|
||||
import { Campaigns } from "./campaign";
|
||||
|
||||
const defaultBaseUrl = "https://app.usesend.com";
|
||||
// eslint-disable-next-line turbo/no-undeclared-env-vars
|
||||
@@ -18,6 +19,7 @@ export class UseSend {
|
||||
readonly emails = new Emails(this);
|
||||
readonly domains = new Domains(this);
|
||||
readonly contacts = new Contacts(this);
|
||||
readonly campaigns = new Campaigns(this);
|
||||
url = baseUrl;
|
||||
|
||||
constructor(
|
||||
|
||||
Vendored
+276
@@ -959,6 +959,282 @@ export interface paths {
|
||||
};
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/campaigns": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
name: string;
|
||||
from: string;
|
||||
subject: string;
|
||||
previewText?: string;
|
||||
contactBookId: string;
|
||||
content?: string;
|
||||
html?: string;
|
||||
replyTo?: string | string[];
|
||||
cc?: string | string[];
|
||||
bcc?: string | string[];
|
||||
sendNow?: boolean;
|
||||
/** @description Timestamp in ISO 8601 format or natural language (e.g., 'tomorrow 9am', 'next monday 10:30') */
|
||||
scheduledAt?: string;
|
||||
batchSize?: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Create a campaign */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
id: string;
|
||||
name: string;
|
||||
from: string;
|
||||
subject: string;
|
||||
previewText: string | null;
|
||||
contactBookId: string | null;
|
||||
html: string | null;
|
||||
content: string | null;
|
||||
status: string;
|
||||
/** Format: date-time */
|
||||
scheduledAt: string | null;
|
||||
batchSize: number;
|
||||
batchWindowMinutes: number;
|
||||
total: number;
|
||||
sent: number;
|
||||
delivered: number;
|
||||
opened: number;
|
||||
clicked: number;
|
||||
unsubscribed: number;
|
||||
bounced: number;
|
||||
hardBounced: number;
|
||||
complained: number;
|
||||
replyTo: string[];
|
||||
cc: string[];
|
||||
bcc: string[];
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
/** Format: date-time */
|
||||
updatedAt: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/campaigns/{campaignId}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
campaignId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Get campaign details */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
id: string;
|
||||
name: string;
|
||||
from: string;
|
||||
subject: string;
|
||||
previewText: string | null;
|
||||
contactBookId: string | null;
|
||||
html: string | null;
|
||||
content: string | null;
|
||||
status: string;
|
||||
/** Format: date-time */
|
||||
scheduledAt: string | null;
|
||||
batchSize: number;
|
||||
batchWindowMinutes: number;
|
||||
total: number;
|
||||
sent: number;
|
||||
delivered: number;
|
||||
opened: number;
|
||||
clicked: number;
|
||||
unsubscribed: number;
|
||||
bounced: number;
|
||||
hardBounced: number;
|
||||
complained: number;
|
||||
replyTo: string[];
|
||||
cc: string[];
|
||||
bcc: string[];
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
/** Format: date-time */
|
||||
updatedAt: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
put?: never;
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/campaigns/{campaignId}/schedule": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
campaignId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": {
|
||||
/** @description Timestamp in ISO 8601 format or natural language (e.g., 'tomorrow 9am', 'next monday 10:30') */
|
||||
scheduledAt?: string;
|
||||
batchSize?: number;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Schedule a campaign */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
success: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/campaigns/{campaignId}/pause": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
campaignId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Pause a campaign */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
success: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/v1/campaigns/{campaignId}/resume": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path: {
|
||||
campaignId: string;
|
||||
};
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description Resume a campaign */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": {
|
||||
success: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
}
|
||||
export type webhooks = Record<string, never>;
|
||||
export interface components {
|
||||
|
||||
Reference in New Issue
Block a user