Campaigns¶
A campaign groups related articles and order items under a shared brief and questionnaire.
client.campaigns # CampaignsResource
Methods overview¶
Method |
HTTP |
Scope |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
list¶
def list(
*,
limit: int = 25,
page: int = 1,
sort_by: str | None = None,
order_by: str | None = None,
filters: dict | None = None,
as_json: bool | None = None,
) -> Paginated[Campaign] | dict
Returns a Paginated envelope of Campaign.
filters: search (str) — partial match on campaign name.
Example
camps = client.campaigns.list(filters={"search": "launch"})
for c in camps.records:
print(c.name, c.total_articles)
get¶
def get(
campaign_id: str,
*,
as_json: bool | None = None,
) -> Campaign | dict
Returns Campaign — the full record including nested profile and questionnaire.
create¶
Warning
Not yet exercised against the live API — creates persistent campaign data. See Testing status.
def create(
body: CampaignCreateRequest | BaseModel | dict,
*,
as_json: bool | None = None,
) -> Campaign | dict
Returns Campaign — the newly created campaign.
Request body (CampaignCreateRequest):
Field |
Type |
Notes |
|---|---|---|
|
|
Required |
|
|
Required — send |
|
|
Required |
|
|
Required |
|
|
Required — send |
|
|
Required — send |
|
|
Required — send |
|
|
Required — send |
|
|
Required — send |
Unusual: Presscart’s schema expects all nine keys to be present in the payload, but most may be
null.pypresscart’sCampaignCreateRequestusesexclude_none=Trueby default — pass a dict to preserve explicit nulls (create({"name": ..., "keywords": None, ...})).
Example
from pypresscart import CampaignCreateRequest
campaign = client.campaigns.create(
CampaignCreateRequest(
name="Q3 Launch",
description="Announce v2.0",
profile_id="prof_1",
objectives="drive awareness",
keywords="AI, SaaS, launch",
target_audience="VPs of Engineering",
tone="authoritative",
writing_samples=None,
file_id=None,
)
)
update¶
Warning
Not yet exercised against the live API — mutates an existing campaign on the live dashboard. See Testing status.
def update(
campaign_id: str,
body: CampaignUpdateRequest | BaseModel | dict,
*,
as_json: bool | None = None,
) -> Campaign | dict
Returns Campaign — the updated campaign.
All fields on CampaignUpdateRequest are optional — only send what you’re changing.
from pypresscart import CampaignUpdateRequest
client.campaigns.update("cmp_1", CampaignUpdateRequest(tone="playful"))
list_articles¶
def list_articles(
campaign_id: str,
*,
limit: int = 25,
page: int = 1,
sort_by: str | None = None,
order_by: str | None = None,
as_json: bool | None = None,
) -> Paginated[CampaignArticleRow] | dict
Returns a Paginated envelope of CampaignArticleRow. Each row includes the assigned writer, current status, and the article’s brief/draft/live URLs.
article_status_counts¶
def article_status_counts(
campaign_id: str,
*,
as_json: bool | None = None,
) -> dict
Returns a plain dict — this endpoint has a non-standard envelope so we don’t wrap it. Individual entries match ArticleStatusCount if you need typed access.
This endpoint returns a non-standard envelope and is always returned as a
dict, regardless ofresponse_mode:{ "records": [ { "name": "In Progress", "prefix": "...", "id": "...", "count": 3 }, ... ] }Individual entries can be materialized as
ArticleStatusCountviaArticleStatusCount.model_validate(entry)if you want typed access.
assign_order_items¶
Attach existing order items to a campaign.
Warning
Not yet exercised against the live API — mutates campaign-to-order-item associations. See Testing status.
def assign_order_items(
campaign_id: str,
body: AssignOrderItemsRequest | BaseModel | dict,
*,
as_json: bool | None = None,
) -> dict
Returns a plain dict with shape {"records": [{"id": "...", "campaign_id": "..."}, ...]} — non-standard envelope, always a dict.
Body: {"order_item_ids": ["oi_1", "oi_2"]}
from pypresscart import AssignOrderItemsRequest
client.campaigns.assign_order_items(
"cmp_1",
AssignOrderItemsRequest(order_item_ids=["oi_a", "oi_b"]),
)
link_questionnaire¶
Link an uploaded file to the campaign’s questionnaire (for writing samples, brand guides, etc.).
Warning
Not yet exercised against the live API — mutates questionnaire state. See Testing status.
def link_questionnaire(
campaign_id: str,
body: QuestionnaireLinkRequest | BaseModel | dict,
*,
as_json: bool | None = None,
) -> Questionnaire | dict
Returns Questionnaire — the updated questionnaire.
Body (QuestionnaireLinkRequest):
Field |
Type |
|---|---|
|
|
|
|
|
|
|
|
Typical flow:
uploaded = client.files.upload("brand-guide.pdf").files[0]
client.campaigns.link_questionnaire(
"cmp_1",
{
"file_id": uploaded.file_key,
"file_url": uploaded.file_url,
"file_name": uploaded.name,
"file_size": uploaded.size,
},
)
Recipes¶
End-to-end campaign setup¶
# 1. Create the campaign
c = client.campaigns.create(
CampaignCreateRequest(
name="Q3 Launch",
description="Announce v2.0",
profile_id="prof_1",
objectives="drive awareness",
keywords="AI, SaaS",
target_audience="VPs of Engineering",
tone="authoritative",
writing_samples=None,
file_id=None,
)
)
# 2. Place the orders first (see Resource: Orders)
order = client.orders.create_checkout({...})
# 3. Assign the order items to this campaign
order_item_ids = [li.id for li in order.line_items]
client.campaigns.assign_order_items(c.id, {"order_item_ids": order_item_ids})
Progress dashboard¶
counts = client.campaigns.article_status_counts("cmp_1")
for row in counts["records"]:
print(f"{row['name']:20} {row['count']}")