Workspace API

Newsletter content

Newsletter content endpoints of the Zanfia Workspace API, with schemas and code samples.

5 min readLast updated Sep 10, 2026

Content of Newsletter products, addressed by the product id: the archived issue list (creator view, hidden issues included), per-issue visibility, render mode and cover, newsletter settings, and issue authoring. Issues normally arrive by sending emails; the API can also write a post without sending: POST …/issues creates a hidden article-first issue, PUT …/issues/{issueId}/draft holds the Markdown draft, POST …/draft/publish makes it live. Drafts never touch the published fields until publish. All routes require a Authorization: Bearer header — see Authentication.

List newsletter issues

GET/products/{productId}/newsletter/issues

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

Query Parameters

cursor?string

Opaque cursor from a previous page.

limit?integer

Page size 1-50 (default 20).

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string/newsletter/issues"
{  "items": [    {      "id": "string",      "emailId": "string",      "subject": "string",      "slug": "string",      "status": "public",      "landingPageVisibility": "public",      "renderMode": "snapshot",      "source": "email-loop",      "thumbnailUrl": "string",      "hasUnpublishedDraft": true,      "createdAt": "string"    }  ],  "nextCursor": "string",  "hasMore": true}
{  "error": "string",  "message": "string"}

Create an issue without sending

POST/products/{productId}/newsletter/issues

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

"Write a post without sending": creates a HIDDEN, article-first issue with empty content. Fill it in via the draft routes, then publish the draft.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/newsletter/issues" \  -H "Content-Type: application/json" \  -d '{    "subject": "string"  }'
{  "issue": {    "id": "string",    "emailId": "string",    "subject": "string",    "slug": "string",    "status": "public",    "landingPageVisibility": "public",    "renderMode": "snapshot",    "source": "email-loop",    "thumbnailUrl": "string",    "hasUnpublishedDraft": true,    "createdAt": "string"  }}
{  "error": "string",  "message": "string"}

Copy issues to other newsletters

POST/products/{productId}/newsletter/issues/copy

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/newsletter/issues/copy" \  -H "Content-Type: application/json" \  -d '{    "issueIds": [      "string"    ],    "targetProductIds": [      "string"    ]  }'
{  "copied": [    {      "productId": "string",      "newsletterId": "string",      "issueIds": [        "string"      ]    }  ],  "skipped": [    {      "productId": "string",      "reason": "product-not-found"    }  ]}
{  "error": "string",  "message": "string"}

Update issue visibility & cover

PATCH/products/{productId}/newsletter/issues/{issueId}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

issueId*string

Newsletter issue id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/products/string/newsletter/issues/string" \  -H "Content-Type: application/json" \  -d '{}'
{  "issueId": "string",  "updated": true}
{  "error": "string",  "message": "string"}

Delete an issue

DELETE/products/{productId}/newsletter/issues/{issueId}

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

issueId*string

Newsletter issue id

Response Body

application/json

application/json

curl -X DELETE "https://example.com/products/string/newsletter/issues/string"
{  "issueId": "string",  "deleted": true}
{  "error": "string",  "message": "string"}

Save an issue draft

PUT/products/{productId}/newsletter/issues/{issueId}/draft

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

issueId*string

Newsletter issue id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Unpublished draft fields of an issue. Presence-based: only the keys sent are written — a subject-only save never wipes a pending content draft; an explicit null clears that one draft field. At least one key required.

Response Body

application/json

application/json

curl -X PUT "https://example.com/products/string/newsletter/issues/string/draft" \  -H "Content-Type: application/json" \  -d '{}'
{  "issueId": "string",  "draft": {    "subject": "string",    "articleContent": "string"  }}
{  "error": "string",  "message": "string"}

Discard an issue draft

DELETE/products/{productId}/newsletter/issues/{issueId}/draft

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

issueId*string

Newsletter issue id

Response Body

application/json

application/json

curl -X DELETE "https://example.com/products/string/newsletter/issues/string/draft"
{  "issueId": "string",  "discarded": true}
{  "error": "string",  "message": "string"}

Publish an issue draft

POST/products/{productId}/newsletter/issues/{issueId}/draft/publish

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

issueId*string

Newsletter issue id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/newsletter/issues/string/draft/publish" \  -H "Content-Type: application/json" \  -d '{}'
{  "issueId": "string",  "promotion": {    "subject": "string",    "articleContent": "string",    "renderMode": "snapshot",    "slug": "string",    "status": "public"  }}
{  "error": "string",  "message": "string"}

Update newsletter settings

PATCH/products/{productId}/newsletter/settings

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

productId*string

Product id

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Partial settings patch. archive merges per-field over the current config; the other blocks replace whole. At least one block is required.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/products/string/newsletter/settings" \  -H "Content-Type: application/json" \  -d '{}'
{  "updated": true}
{  "error": "string",  "message": "string"}

Was this article helpful?

Related articles

Spotted something off? Tell us at support@zanfia.com.