Workspace API

Produkty

Endpointy „Produkty” Zanfia Workspace API — ze schematami i przykładami kodu.

14 min czytaniaOstatnia aktualizacja: 24 paź 2026

Twórz, edytuj, publikuj i wyceniaj produkty. Wszystkie endpointy wymagają nagłówka Authorization: Bearer — zobacz Uwierzytelnianie.

Lista produktów

GET/products

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/products"
{  "count": 0,  "products": [    {      "id": "string",      "name": "string",      "slug": "string",      "productType": "course",      "status": "draft",      "isFree": true,      "createdAt": "string"    }  ]}
{  "error": "string",  "message": "string"}

Utwórz produkt

POST/products

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

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" \  -H "Content-Type: application/json" \  -d '{    "name": "string",    "productType": "course"  }'
{  "id": "string",  "name": "string",  "slug": "string",  "productType": "course",  "status": "draft",  "isFree": true,  "createdAt": "string",  "defaultCheckoutId": "string"}
{  "error": "string",  "message": "string"}

Szczegóły produktu

GET/products/{productId}

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string"
{  "id": "string",  "name": "string",  "slug": "string",  "productType": "course",  "status": "draft",  "isFree": true,  "createdAt": "string",  "description": "string",  "clientCount": 0,  "plans": [    {      "id": "string",      "name": "string",      "description": "string",      "active": true,      "isDefault": true,      "order": 0,      "includedProducts": [        {          "productId": "string",          "productName": "string",          "productType": "course"        }      ],      "communityRoleGrants": {        "property1": [          "string"        ],        "property2": [          "string"        ]      },      "createdAt": "string",      "updatedAt": "string"    }  ],  "storefrontVisibility": "public",  "language": "pl"}
{  "error": "string",  "message": "string"}

Aktualizuj informacje o produkcie

PATCH/products/{productId}

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 update of a product's display info. Omitted fields are left unchanged.

Response Body

application/json

application/json

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

Delete product

DELETE/products/{productId}

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X DELETE "https://example.com/products/string"
{  "productId": "string",  "status": "draft",  "purgeAfter": 0,  "runId": "string",  "activeGrants": 0,  "cancellableSubscriptions": 0}
{  "error": "string",  "message": "string"}

Duplikuj produkt

POST/products/{productId}/duplicate

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.

POST /products/:productId/duplicate — copy a product as a new DRAFT: its settings, description, plans, every non-archived offer (fresh price ids, never shared with the source) and its content (course sections, lessons and quizzes; downloads; event / consultation / service config). Customers, orders, access and stats are not copied; the slug gets a -kopia (Polish product) or -copy suffix. Community, knowledge base and newsletter products answer 422 unsupported-product-type.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/duplicate" \  -H "Content-Type: application/json" \  -d '{}'
{  "id": "string",  "name": "string",  "slug": "string",  "productType": "course",  "status": "draft",  "isFree": true,  "createdAt": "string",  "defaultCheckoutId": "string",  "skippedCheckoutIds": [    "string"  ]}
{  "error": "string",  "message": "string"}

Archiwizuj produkt

POST/products/{productId}/archive

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/archive"
{  "productId": "string",  "status": "draft"}
{  "error": "string",  "message": "string"}

Opublikuj lub cofnij publikację produktu

POST/products/{productId}/status

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/status" \  -H "Content-Type: application/json" \  -d '{    "status": "draft"  }'
{  "productId": "string",  "status": "draft"}
{  "error": "string",  "message": "string"}

Ustawienia rezerwacji

GET/products/{productId}/appointment

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string/appointment"
{  "productType": "consultation",  "consultation": {    "bookingMethod": "native",    "bookingUrl": "string",    "duration": 0,    "location": "string",    "locationDetails": "string",    "confirmationMessage": "string",    "showOnSuccessPage": true,    "availability": [      {        "dayOfWeek": 0,        "startTime": "string",        "endTime": "string"      }    ],    "exceptions": [      "string"    ],    "bufferMinutes": 0,    "maxBookingsPerDay": 0,    "maxBookingsPerWeek": 0,    "minNoticeHours": 0,    "bookingWindowDays": 0,    "sessionsPerPurchase": 0,    "timezone": "string"  },  "service": {    "deliverables": [      "string"    ],    "deliveryTime": {      "value": 0,      "unit": "days"    },    "revisionRounds": 0,    "briefMethod": "native",    "briefUrl": "string",    "showOnSuccessPage": true,    "briefFields": [      {        "id": "string",        "label": "string",        "type": "shortText",        "required": true,        "options": "string"      }    ]  },  "event": {    "type": "online",    "location": "string",    "startsAt": "string",    "endsAt": "string",    "capacity": 0,    "showOnSuccessPage": true,    "liveRoomId": "string"  }}
{  "error": "string",  "message": "string"}

Aktualizuj ustawienia rezerwacji

PATCH/products/{productId}/appointment

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.

Upsert an appointment product's content config. Provide EXACTLY ONE of the three sub-objects, and it must match the product's own type (else 400/409).

Response Body

application/json

application/json

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

Lista rezerwacji konsultacji

GET/consultations/bookings

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Query Parameters

productId?string

One consultation product; omit for every consultation of the workspace.

from?string

Range start (inclusive): ISO 8601 date-time or YYYY-MM-DD (UTC). Default: today 00:00 UTC.

to?string

Range end (exclusive): ISO 8601 date-time or YYYY-MM-DD (= end of that day, UTC). Default: from + 30 days.

status?string

booked = not ended yet, done = already ended, cancelled. Omit for all.

Value in

  • "booked"
  • "cancelled"
  • "done"
limit?integer

Page size, max 100 (default 50).

cursor?string

The previous page's nextCursor.

Response Body

application/json

application/json

curl -X GET "https://example.com/consultations/bookings"
{  "items": [    {      "bookingId": "string",      "startAt": "string",      "endAt": "string",      "durationMinutes": 0,      "clientEmail": "string",      "clientName": "string",      "productId": "string",      "productName": "string",      "status": "booked",      "clientId": "string",      "clientTimezone": "string",      "timezone": "string",      "location": "string",      "locationDetails": "string",      "bookedAt": "string",      "cancelledAt": "string",      "cancelledBy": "creator"    }  ],  "nextCursor": "string",  "from": "string",  "to": "string"}
{  "error": "string",  "message": "string"}

Lista kupujących konsultację bez rezerwacji

GET/consultations/clients-without-booking

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Query Parameters

productId?string

One consultation product; omit for every consultation of the workspace.

limit?integer

Page size, max 100 (default 50).

cursor?string

The previous page's nextCursor.

Response Body

application/json

application/json

curl -X GET "https://example.com/consultations/clients-without-booking"
{  "items": [    {      "productId": "string",      "productName": "string",      "clientId": "string",      "clientName": "string",      "clientEmail": "string",      "accessGrantedAt": "string"    }  ],  "nextCursor": "string"}
{  "error": "string",  "message": "string"}

Ustawienia po zakupie

GET/products/{productId}/after-purchase

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string/after-purchase"
{  "settings": {    "thankYou": {      "type": "defaultPage",      "redirectUrl": "string",      "appendEmailSha256": true,      "custom": {        "eyebrow": "string",        "headline": "string",        "messageHtml": "string",        "messageMarkdown": "string",        "ctaLabel": "string",        "ctaUrl": "string",        "showOrderSummary": true,        "nextOffer": {          "kind": "checkout",          "checkoutId": "string",          "productId": "string",          "headline": "string",          "description": "string",          "ctaLabel": "string"        }      }    },    "emails": {      "sendPurchaseConfirmationToBuyer": true,      "sendPurchaseNotificationToOwner": true,      "sendFailedPaymentEmailToBuyer": true,      "sendFailedPaymentEmailToOwner": true    },    "emailOverrides": {      "property1": {        "enabled": true,        "subject": {          "en": "string",          "pl": "string"        },        "headline": {          "en": "string",          "pl": "string"        },        "layout": [          {            "id": "string",            "type": "text",            "text": {              "en": "string",              "pl": "string"            }          }        ],        "body": {          "en": "string",          "pl": "string"        },        "variants": {          "property1": {},          "property2": {}        },        "attachments": [          {            "kind": "media",            "mediaId": "string",            "name": "string",            "mimeType": "string",            "size": 0,            "storagePath": "string",            "url": "string"          }        ]      },      "property2": {        "enabled": true,        "subject": {          "en": "string",          "pl": "string"        },        "headline": {          "en": "string",          "pl": "string"        },        "layout": [          {            "id": "string",            "type": "text",            "text": {              "en": "string",              "pl": "string"            }          }        ],        "body": {          "en": "string",          "pl": "string"        },        "variants": {          "property1": {},          "property2": {}        },        "attachments": [          {            "kind": "media",            "mediaId": "string",            "name": "string",            "mimeType": "string",            "size": 0,            "storagePath": "string",            "url": "string"          }        ]      }    }  }}
{  "error": "string",  "message": "string"}

Aktualizuj ustawienia po zakupie

PATCH/products/{productId}/after-purchase

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 write of the product's shared after-purchase defaults. Omitted sections keep their stored value (the defaults are configured progressively). Written sections are mirrored onto every non-overriding offer of the product.

Response Body

application/json

application/json

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

Zastąp zdjęcia produktu

PUT/products/{productId}/images

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.

Full replace of a product's cover image array. Each entry must be an https URL ALREADY hosted (upload to the Media Library first — POST /media — and use its returned url; this route only writes the product's images array and best-effort syncs them to the linked Stripe Product). Certificate / generated cover fields are not editable here.

Response Body

application/json

application/json

curl -X PUT "https://example.com/products/string/images" \  -H "Content-Type: application/json" \  -d '{    "images": [      "string"    ]  }'
{  "images": [    "string"  ]}
{  "error": "string",  "message": "string"}

Lista cen produktu

GET/products/{productId}/prices

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string/prices"
{  "count": 0,  "prices": [    {      "id": "string",      "productId": "string",      "amountCents": 0,      "currency": "string",      "type": "one_time",      "active": true,      "status": "available",      "gateways": [        "string"      ],      "label": "string"    }  ]}
{  "error": "string",  "message": "string"}

Dodaj cenę produktu

POST/products/{productId}/prices

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.

Create a one-time, single-currency paid price on the product's default checkout (creating the checkout if none exists). The Stripe price is created server-side; if no payment gateway is connected yet the price is stored unregistered (empty gateways) and registered when the offer is published.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/prices" \  -H "Content-Type: application/json" \  -d '{    "amountCents": 0,    "currency": "string"  }'
{  "id": "string",  "productId": "string",  "amountCents": 0,  "currency": "string",  "type": "one_time",  "active": true,  "status": "available",  "gateways": [    "string"  ],  "label": "string"}
{  "error": "string",  "message": "string"}

Zastąp plany i pakiety

PUT/products/{productId}/plans

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.

Full replace of a product's plans[] (plans & bundling). Mirrors the internal UpdateProductPlansRequestDTO: the caller sends the complete desired state; the server generates ids for new plans, owns timestamps, and enforces the invariants (unique ids, at most one default, no self-include, one level of bundling both directions). Checkout prices still linked to a removed plan are unlinked in the same call (they resolve to the default plan); upgrade offers touching it are deactivated.

Response Body

application/json

application/json

curl -X PUT "https://example.com/products/string/plans" \  -H "Content-Type: application/json" \  -d '{    "plans": [      {        "name": "string",        "active": true,        "includedProducts": [          {            "productId": "string",            "productName": "string"          }        ]      }    ]  }'
{  "productId": "string",  "plans": [    {      "id": "string",      "name": "string",      "description": "string",      "active": true,      "isDefault": true,      "order": 0,      "includedProducts": [        {          "productId": "string",          "productName": "string",          "productType": "course"        }      ],      "communityRoleGrants": {        "property1": [          "string"        ],        "property2": [          "string"        ]      },      "createdAt": "string",      "updatedAt": "string"    }  ]}
{  "error": "string",  "message": "string"}

Policz klientów wg planu

POST/products/{productId}/plans/count-clients

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.

Count the product's active customers whose EFFECTIVE plan is planId (grant match, falling back to the default plan — the same resolution the access checks use). Omit planId to size a not-yet-saved first/default plan: every active grant counts.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/plans/count-clients" \  -H "Content-Type: application/json" \  -d '{}'
{  "count": 0}
{  "error": "string",  "message": "string"}

Uzupełnij członków społeczności dla planu

POST/products/{productId}/plans/backfill-community-members

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.

Eagerly create community-member docs for every active customer whose effective plan includes communityProductId — sends membership grants, so run it deliberately (typically right after adding a community to a plan). Idempotent: existing members are left untouched. Answers 202 at once; a background run adds the members.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/plans/backfill-community-members" \  -H "Content-Type: application/json" \  -d '{    "communityProductId": "string"  }'
{  "status": "started",  "eligibleClients": 0,  "runId": "string"}
{  "error": "string",  "message": "string"}

Zmień plan klienta

POST/products/{productId}/clients/plan

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.

Move a client's grant to a different plan on a multi-plan product. Billing-neutral: only grant.planId moves; community membership is reconciled server-side as part of the same request.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/clients/plan" \  -H "Content-Type: application/json" \  -d '{    "clientId": "string",    "planId": "string"  }'
{  "clientId": "string",  "planId": "string",  "membership": {    "added": 0,    "alreadyMembers": 0,    "skipped": 0,    "removed": 0  }}
{  "error": "string",  "message": "string"}

Rename download file

PATCH/products/{productId}/downloads/files/{uid}

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

uid*string

Download file uid

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

New label of one attached file; it is also the buyer's download filename (max 255 characters).

Response Body

application/json

application/json

curl -X PATCH "https://example.com/products/string/downloads/files/string" \  -H "Content-Type: application/json" \  -d '{    "name": "string"  }'
{  "file": {    "url": "string",    "name": "string",    "uid": "string",    "mediaId": "string",    "size": 0  },  "files": [    {      "url": "string",      "name": "string",      "uid": "string",      "mediaId": "string",      "size": 0    }  ]}
{  "error": "string",  "message": "string"}

Pobierz pliki produktu

GET/products/{productId}/file-set

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string/file-set"
{  "productId": "string",  "revision": 0,  "fileCount": 0,  "totalBytes": 0,  "lastMessage": "string",  "updatedAt": "string",  "files": [    {      "path": "string",      "size": 0,      "contentType": "string",      "sha256": "string",      "updatedAt": "string"    }  ]}
{  "error": "string",  "message": "string"}

Zmień pliki produktu

POST/products/{productId}/file-set

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.

POST /products/:productId/file-set on the Workspace API.

Response Body

application/json

application/json

curl -X POST "https://example.com/products/string/file-set" \  -H "Content-Type: application/json" \  -d '{}'
{  "revision": 0,  "added": [    "string"  ],  "updated": [    "string"  ],  "unchanged": [    "string"  ],  "deleted": [    "string"  ],  "fileCount": 0,  "totalBytes": 0}
{  "error": "string",  "message": "string"}

Podgląd powiadomienia do kupujących produkt

POST/products/{productId}/buyers-notifications/preview

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/buyers-notifications/preview" \  -H "Content-Type: application/json" \  -d '{}'
{  "recipientCount": 0,  "link": "string",  "canSend": true,  "blockedBy": "product_cooldown",  "nextAllowedAt": "string",  "sentToday": 0,  "dailyCap": 0,  "emailSkipped": "email_limit_reached",  "emailRemaining": 0,  "emailResetsAt": "string"}
{  "error": "string",  "message": "string"}

Historia powiadomień kupujących produktu

GET/products/{productId}/buyers-notifications

Authorization

bearerAuth
AuthorizationBearer <token>

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

In: header

Path Parameters

productId*string

Product id

Query Parameters

limit?integer

Newest first; default 20, max 50.

Range1 <= value <= 50

Response Body

application/json

application/json

curl -X GET "https://example.com/products/string/buyers-notifications"
{  "items": [    {      "id": "string",      "productId": "string",      "productName": "string",      "title": "string",      "body": "string",      "link": "string",      "sendEmail": true,      "emailSkipped": "email_limit_reached",      "status": "queued",      "createdAt": "string",      "finishedAt": "string",      "confirmedRecipientCount": 0,      "counts": {        "recipients": 0,        "bells": 0,        "pushes": 0,        "emails": 0,        "optedOut": 0      }    }  ]}
{  "error": "string",  "message": "string"}

Powiadom kupujących produkt

POST/products/{productId}/buyers-notifications

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/buyers-notifications" \  -H "Content-Type: application/json" \  -d '{    "sendId": "string",    "title": "string",    "body": "string",    "sendEmail": true,    "confirmedRecipientCount": 0  }'
{  "notification": {    "id": "string",    "productId": "string",    "productName": "string",    "title": "string",    "body": "string",    "link": "string",    "sendEmail": true,    "emailSkipped": "email_limit_reached",    "status": "queued",    "createdAt": "string",    "finishedAt": "string",    "confirmedRecipientCount": 0,    "counts": {      "recipients": 0,      "bells": 0,      "pushes": 0,      "emails": 0,      "optedOut": 0    }  },  "alreadySent": true}
{  "error": "string",  "message": "string"}

Czy ten artykuł był pomocny?

Powiązane artykuły

Coś się nie zgadza? Napisz do nas na support@zanfia.com.