Cria ou executa products
POST/api/products
- Auth
- Jeton requis
- Qui peut l’appeler:
- owner
- admin
- Clé d’API:
- store:write
- X-CommunityId
X-CommunityIdEnvoyez le X-CommunityId de la communauté où l’opération a lieu.
Toda opção de cobrança pertence a um plano. `type = SUBSCRIPTION` sem `prerequisiteGroupIds` (não é adicional) e sem `subscriptionGroupIds` responde 400 com `param = subscriptionGroupIds`. Para criar um adicional, envie `prerequisiteGroupIds` (os planos que o aceitam). Estoque (E1): `hasStock` sem `stockQuantity` responde 400 (`param = stockQuantity`); `hasStock` em `SUBSCRIPTION`, 400 (`param = hasStock`). Owner ou admin. Aceita, entre os demais campos, `directLinkEnabled` (boolean opcional, padrão `false`): com ele ligado, um produto avulso (`ONE_TIME` ou `INSTALLMENT`) pode ser comprado por link direto e aparece em `GET /checkout/products`. Desligado, só é comprável por quem enxerga um space Loja (`storefront`) que o mostra. Assinaturas ignoram a flag. `prerequisiteGroupIds` (array de UUID opcional) torna o produto um adicional: ele só aparece nas listagens públicas e só é vendido a quem tem assinatura ACTIVE ou TRIALING num desses grupos, e a assinatura do adicional acompanha a do plano. Os grupos precisam ser da comunidade (senão 400, `param = prerequisiteGroupIds`) e não podem incluir um grupo em `subscriptionGroupIds` (400). A resposta traz `prerequisiteGroupIds`. **Obsoleto na escrita:** a lista agora é escrita pelo plano (`addOnProductIds` em `POST`/`PUT /subscription-groups`), sobre a mesma relação. Este campo continua aceito e gravando, e continua nas respostas. `commitmentMonths` (inteiro de 1 a 36, ou `null`) é a duração do contrato (fidelidade): só vale para `SUBSCRIPTION` com `billingInterval` `MONTHLY` (senão 400, `param = commitmentMonths`); `null` ou ausente = sem contrato. A resposta traz `commitmentMonths`. `installmentInterestPayer` (`BUYER`, o padrão, ou `ORGANIZATION`) diz quem paga os juros de parcelamento da Memberfy no cartão: `BUYER` soma ao preço, `ORGANIZATION` cobra o preço e desconta da comunidade. A resposta traz o campo. **Rascunho sem aprovação (2026-10-06):** criar não exige mais informações comerciais aprovadas. O produto nasce sempre `DRAFT`, e a moeda (`currency` na resposta) sai do país das informações comerciais em qualquer status (`PENDING`, `IN_REVIEW`, `REJECTED` ou `APPROVED`); sem informações comerciais, `BRL`. O que exige aprovação é publicar (`POST .../publish` ou `PUT` com `status: ACTIVE`). **Slug:** sem `slug`, ele sai do título e ganha sufixo (`-1`, `-2`…) quando já está em uso, inclusive por um produto excluído. Um `slug` enviado que já está em uso (por produto ativo ou excluído) responde 400 com `param = slug`; duas criações simultâneas com o mesmo slug respondem 409 com `param = slug`. A resposta traz `pricingMode` e `pointsPrice`.
En-têtes
| Nom | Type | Description |
|---|---|---|
X-CommunityIdfacultatif | string (uuid) | ID da comunidade em que a operação acontece. Obrigatório na maioria dos endpoints com escopo de comunidade. |
Corps de la requête application/json
La spécification ne déclare pas les champs de ce corps (un envoi multipart, par exemple). Consultez le guide du thème.
Réponses
| Statut | Description |
|---|---|
201 | Operação realizada com sucesso. |
400 | Requisição inválida — falha de validação. |
401 | Token ausente, inválido ou expirado; token de outra comunidade (o `X-CommunityId` ou o `communityId` do corpo não é o do token); token antigo ou de uma sessão encerrada (troca de senha, convite aceito). Nesses casos a mensagem pede para entrar de novo (`auth.signInAgain`). |
403 | Autenticado, mas sem permissão para esta operação. |
404 | Recurso não encontrado. |
409 | Requisição inválida — falha de validação. |
500 | Erro interno do servidor. |
Exemple curl
curl -X POST "https://api.memberfy.net/api/products" \
-H "Authorization: Bearer $TOKEN" \
-H "X-CommunityId: $COMMUNITY_ID" \
-H "Content-Type: application/json" \
-d '"string"'